summaryrefslogtreecommitdiff
path: root/libs/pbd3
diff options
context:
space:
mode:
Diffstat (limited to 'libs/pbd3')
-rw-r--r--libs/pbd3/.cvsignore3
-rw-r--r--libs/pbd3/AUTHORS0
-rw-r--r--libs/pbd3/COPYING340
-rw-r--r--libs/pbd3/ChangeLog6
-rw-r--r--libs/pbd3/NEWS0
-rw-r--r--libs/pbd3/README0
-rw-r--r--libs/pbd3/SConscript44
-rw-r--r--libs/pbd3/basename.cc47
-rw-r--r--libs/pbd3/dirname.cc51
-rw-r--r--libs/pbd3/dmalloc.cc102
-rw-r--r--libs/pbd3/ftw.cc220
-rw-r--r--libs/pbd3/libpbd.pc.in11
-rw-r--r--libs/pbd3/libpbd.spec.in70
-rw-r--r--libs/pbd3/mountpoint.cc113
-rw-r--r--libs/pbd3/pathscanner.cc201
-rw-r--r--libs/pbd3/pbd-config.in232
-rw-r--r--libs/pbd3/pbd/.DS_Storebin0 -> 6148 bytes
-rw-r--r--libs/pbd3/pbd/.cvsignore1
-rw-r--r--libs/pbd3/pbd/abstract_ui.h67
-rw-r--r--libs/pbd3/pbd/atomic.h1232
-rw-r--r--libs/pbd3/pbd/basename.h15
-rw-r--r--libs/pbd3/pbd/compose.h393
-rw-r--r--libs/pbd3/pbd/datum.h57
-rw-r--r--libs/pbd3/pbd/dirname.h11
-rw-r--r--libs/pbd3/pbd/ellipsoid.h74
-rw-r--r--libs/pbd3/pbd/error.h30
-rw-r--r--libs/pbd3/pbd/failed_constructor.h11
-rw-r--r--libs/pbd3/pbd/fastlog.h38
-rw-r--r--libs/pbd3/pbd/foreach.h42
-rw-r--r--libs/pbd3/pbd/forkexec.h9
-rw-r--r--libs/pbd3/pbd/ftw.h106
-rw-r--r--libs/pbd3/pbd/irix_platform.h20
-rw-r--r--libs/pbd3/pbd/linux_platform.h41
-rw-r--r--libs/pbd3/pbd/lock_free_fifo.h86
-rw-r--r--libs/pbd3/pbd/lockmonitor.h194
-rw-r--r--libs/pbd3/pbd/mountpoint.h28
-rw-r--r--libs/pbd3/pbd/pathscanner.h66
-rw-r--r--libs/pbd3/pbd/platform.h45
-rw-r--r--libs/pbd3/pbd/platform_factory.h12
-rw-r--r--libs/pbd3/pbd/pool.h74
-rw-r--r--libs/pbd3/pbd/position.h38
-rw-r--r--libs/pbd3/pbd/precision_timer.h61
-rw-r--r--libs/pbd3/pbd/pthread_spinlock.h29
-rw-r--r--libs/pbd3/pbd/pthread_utils.h21
-rw-r--r--libs/pbd3/pbd/rcpointer.h61
-rw-r--r--libs/pbd3/pbd/receiver.h50
-rw-r--r--libs/pbd3/pbd/relation.h35
-rw-r--r--libs/pbd3/pbd/restartable_rw.h7
-rw-r--r--libs/pbd3/pbd/ringbuffer.h283
-rw-r--r--libs/pbd3/pbd/ringbufferNPT.h272
-rw-r--r--libs/pbd3/pbd/rt.h25
-rw-r--r--libs/pbd3/pbd/rtthread.h30
-rw-r--r--libs/pbd3/pbd/scale.h53
-rw-r--r--libs/pbd3/pbd/selectable.h102
-rw-r--r--libs/pbd3/pbd/solaris_platform.h41
-rw-r--r--libs/pbd3/pbd/stl_delete.h89
-rw-r--r--libs/pbd3/pbd/stl_functors.h93
-rw-r--r--libs/pbd3/pbd/strsplit.h9
-rw-r--r--libs/pbd3/pbd/strsub.h25
-rw-r--r--libs/pbd3/pbd/textreceiver.h44
-rw-r--r--libs/pbd3/pbd/thread.h127
-rw-r--r--libs/pbd3/pbd/thrown_error.h39
-rw-r--r--libs/pbd3/pbd/touchable.h89
-rw-r--r--libs/pbd3/pbd/transmitter.h109
-rw-r--r--libs/pbd3/pbd/types.h32
-rw-r--r--libs/pbd3/pbd/undo.h96
-rw-r--r--libs/pbd3/pbd/unescape.h6
-rw-r--r--libs/pbd3/pbd/xml++.h127
-rw-r--r--libs/pbd3/pool.cc135
-rw-r--r--libs/pbd3/pthread_utils.cc133
-rw-r--r--libs/pbd3/receiver.cc58
-rw-r--r--libs/pbd3/strsplit.cc41
-rw-r--r--libs/pbd3/textreceiver.cc66
-rw-r--r--libs/pbd3/transmitter.cc115
-rw-r--r--libs/pbd3/undo.cc144
-rw-r--r--libs/pbd3/unescape.cc137
-rw-r--r--libs/pbd3/xml++.cc416
77 files changed, 7330 insertions, 0 deletions
diff --git a/libs/pbd3/.cvsignore b/libs/pbd3/.cvsignore
new file mode 100644
index 0000000000..232255cb47
--- /dev/null
+++ b/libs/pbd3/.cvsignore
@@ -0,0 +1,3 @@
+libpbd.pc
+libpbd.spec
+version.cc
diff --git a/libs/pbd3/AUTHORS b/libs/pbd3/AUTHORS
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/libs/pbd3/AUTHORS
diff --git a/libs/pbd3/COPYING b/libs/pbd3/COPYING
new file mode 100644
index 0000000000..d60c31a97a
--- /dev/null
+++ b/libs/pbd3/COPYING
@@ -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.
diff --git a/libs/pbd3/ChangeLog b/libs/pbd3/ChangeLog
new file mode 100644
index 0000000000..adbde9b0d4
--- /dev/null
+++ b/libs/pbd3/ChangeLog
@@ -0,0 +1,6 @@
+2005-4-1 Taybin Rutkin <taybin@earthlink.net>
+ * Updated to support sigc++-2.0.
+ * Incremented version to 3.0.0.
+
+2004-8-4 Taybin Rutkin <taybin@earthlink.net>
+ * Added support for gcc-3.4
diff --git a/libs/pbd3/NEWS b/libs/pbd3/NEWS
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/libs/pbd3/NEWS
diff --git a/libs/pbd3/README b/libs/pbd3/README
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/libs/pbd3/README
diff --git a/libs/pbd3/SConscript b/libs/pbd3/SConscript
new file mode 100644
index 0000000000..0ab6b72f12
--- /dev/null
+++ b/libs/pbd3/SConscript
@@ -0,0 +1,44 @@
+# -*- python -*-
+
+import glob
+
+Import('env libraries')
+
+pbd3 = env.Copy()
+
+domain = 'libpbd'
+pbd3.Append(DOMAIN=domain,MAJOR=3,MINOR=0,MICRO=1)
+
+pbd3_files = Split("""
+basename.cc
+dirname.cc
+dmalloc.cc
+ftw.cc
+mountpoint.cc
+pathscanner.cc
+pool.cc
+pthread_utils.cc
+receiver.cc
+strsplit.cc
+textreceiver.cc
+transmitter.cc
+undo.cc
+unescape.cc
+version.cc
+xml++.cc
+""")
+
+conf = Configure(pbd3)
+if conf.CheckFunc('getmntent'):
+ conf.env.Append(CCFLAGS="-DHAVE_GETMNTENT")
+pbd3 = conf.Finish()
+
+pbd3.Merge ([ libraries['sigc2'], libraries['xml'] ])
+
+pbd3.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+pbd3.Append(CCFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+
+pbd3.VersionBuild(['version.cc','pbd/version.h'], 'SConscript')
+
+libpbd3 = pbd3.StaticLibrary('pbd', pbd3_files)
+Default(libpbd3)
diff --git a/libs/pbd3/basename.cc b/libs/pbd3/basename.cc
new file mode 100644
index 0000000000..b8c5c64d91
--- /dev/null
+++ b/libs/pbd3/basename.cc
@@ -0,0 +1,47 @@
+#include <iostream>
+#include <string.h>
+#include <pbd/basename.h>
+
+char *
+PBD::basename (const char *path)
+
+{
+ char *slash;
+
+ if ((slash = strrchr (path, '/')) == 0) {
+ return strdup (path);
+ }
+
+ if (*(slash+1) == '\0') {
+ return strdup ("");
+ }
+
+ return strdup (slash+1);
+}
+
+std::string
+PBD::basename (const std::string str)
+{
+ std::string::size_type slash = str.find_last_of ('/');
+
+ if (slash == std::string::npos) {
+ return str;
+ }
+
+ return str.substr (slash+1);
+}
+
+std::string
+PBD::basename_nosuffix (const std::string str)
+{
+ std::string::size_type slash = str.find_last_of ('/');
+ std::string noslash;
+
+ if (slash == std::string::npos) {
+ noslash = str;
+ } else {
+ noslash = str.substr (slash+1);
+ }
+
+ return noslash.substr (0, noslash.find_last_of ('.'));
+}
diff --git a/libs/pbd3/dirname.cc b/libs/pbd3/dirname.cc
new file mode 100644
index 0000000000..8945b6e969
--- /dev/null
+++ b/libs/pbd3/dirname.cc
@@ -0,0 +1,51 @@
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+#include <pbd/dirname.h>
+
+
+char *
+PBD::dirname (const char *path)
+
+{
+ char *slash;
+ size_t len;
+ char *ret;
+
+ if ((slash = strrchr (path, '/')) == 0) {
+ return strdup (path);
+ }
+
+ if (*(slash+1) == '\0') {
+ return strdup ("");
+ }
+
+ len = (size_t) (slash - path);
+ ret = (char *) malloc (sizeof (char) * (len + 1));
+
+ snprintf (ret, len, "%*s", len, path);
+ return ret;
+}
+
+std::string
+PBD::dirname (const std::string str)
+{
+ std::string::size_type slash = str.find_last_of ('/');
+ std::string dir;
+
+ if (slash == std::string::npos) {
+ return str;
+ }
+
+ /* remove trailing multiple slashes (legal under POSIX) */
+
+ dir = str.substr (0, slash);
+ slash = dir.length();
+
+ while (slash > 1 && dir[slash-1] == '/') {
+ slash--;
+ dir = dir.substr (0, slash);
+ }
+
+ return dir;
+}
diff --git a/libs/pbd3/dmalloc.cc b/libs/pbd3/dmalloc.cc
new file mode 100644
index 0000000000..0e730946c8
--- /dev/null
+++ b/libs/pbd3/dmalloc.cc
@@ -0,0 +1,102 @@
+/*
+ * file that facilitates C++ program debugging.
+ *
+ * Copyright 1995 by Gray Watson
+ *
+ * This file is part of the dmalloc package.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * NON-COMMERCIAL purpose and without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies, and that the name of Gray Watson not be used in
+ * advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * Please see the PERMISSIONS file or contact the author for information
+ * about commercial licenses.
+ *
+ * Gray Watson makes no representations about the suitability of the
+ * software described herein for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * The author may be contacted via http://www.letters.com/~gray/
+ *
+ * $Id$
+ */
+
+/*
+ * This file is used to effectively redirect new to the more familiar
+ * malloc and delete to the more familiar free so they can be debugged
+ * with the debug malloc library.. They also give the known error
+ * behavior, too.
+ *
+ * Compile and link this in with the C++ program you want to debug.
+ *
+ * NOTE: I am not a C++ hacker so feedback in the form of other hints
+ * and ideas for C++ users would be much appreciated.
+ */
+
+#ifdef DEBUG_MALLOC
+
+extern "C" {
+#include <stdlib.h>
+#include <dmalloc.h>
+#include "/usr/local/src/dmalloc-4.1.2/return.h"
+}
+
+/*
+ * An overload function for the C++ new.
+ */
+void *
+operator new(size_t size)
+{
+ char *file;
+ GET_RET_ADDR(file);
+
+ /* handle correct C++ semantics for an alloc of size 0 */
+
+ if (size == 0) size = 1;
+
+ return _malloc_leap(file, 0, size);
+}
+
+/*
+ * An overload function for the C++ new[].
+ */
+void *
+operator new[](size_t size)
+{
+ char *file;
+ GET_RET_ADDR(file);
+
+ /* handle correct C++ semantics for an alloc of size 0 */
+
+ if (size == 0) size = 1;
+
+ return _malloc_leap(file, 0, size);
+}
+
+/*
+ * An overload function for the C++ delete.
+ */
+void
+operator delete(void *pnt)
+{
+ char *file;
+ GET_RET_ADDR(file);
+ _free_leap(file, 0, pnt);
+}
+
+/*
+ * An overload function for the C++ delete[]. Thanks to Jens Krinke
+ * <j.krinke@gmx.de>
+ */
+void
+operator delete[](void *pnt)
+{
+ char *file;
+ GET_RET_ADDR(file);
+ _free_leap(file, 0, pnt);
+}
+
+#endif
diff --git a/libs/pbd3/ftw.cc b/libs/pbd3/ftw.cc
new file mode 100644
index 0000000000..ea7162c22e
--- /dev/null
+++ b/libs/pbd3/ftw.cc
@@ -0,0 +1,220 @@
+/*
+ Copyright (c) 2003 by Joel Baker.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the Author nor the names of any contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sys/types.h> /* Because fts(3) says so */
+#include <sys/stat.h>
+#include <fts.h>
+#include <alloca.h>
+
+#include <unistd.h> /* We want strcpy */
+
+#include <cerrno> /* Because errno is our friend */
+
+#ifndef __USE_XOPEN_EXTENDED /* We need nftw values, since we implement it */
+#define __USE_XOPEN_EXTENDED
+#endif
+
+#include <pbd/ftw.h>
+
+/* I like symbolic values - this is only used in this file. */
+
+enum __ftw_modes {
+ MODE_FTW,
+ MODE_NFTW
+};
+
+/* Prototype this so that we can have it later */
+
+static int __ftw_core(const char *, void*, int, int, enum __ftw_modes);
+
+/*
+ * The external function calls are really just wrappers around __ftw_core,
+ * since the work they do is 90% the same.
+ */
+
+int ftw (const char *dir, __ftw_func_t func, int descr) {
+ return __ftw_core(dir, (void*)func, descr, 0, MODE_FTW);
+}
+
+int nftw (const char *dir, __nftw_func_t func, int descr, int flags) {
+ return __ftw_core(dir, (void*)func, descr, flags, MODE_NFTW);
+}
+
+/*
+typedef int (*__ftw_func_t) \
+ (const char *file, const struct stat status, int flag);
+typedef int (*__nftw_func_t) \
+ (const char *file, const struct stat status, int flag, struct FTW detail);
+*/
+
+static int __ftw_core(const char *dir, void* func, int descr, int flags,
+ enum __ftw_modes mode) {
+ FTS *hierarchy = 0;
+ FTSENT *entry = 0;
+ int fts_options;
+ char *paths[2];
+ int ftw_flag = 0, func_ret = 0;
+ struct FTW ftw_st;
+ int skip_entry;
+ __ftw_func_t ftw_func;
+ __nftw_func_t nftw_func;
+
+ /* We need at least one descriptor to call fts */
+
+ if (descr < 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Decide which mode we're running in, and set the FTS options suitably. */
+
+ if (MODE_NFTW == mode) { /* NFTW mode, with all the bells and whistles. */
+ fts_options = (flags & FTW_PHYS) ? FTS_PHYSICAL : FTS_LOGICAL;
+ fts_options |= (flags & FTW_CHDIR) ? FTS_NOCHDIR : 0;
+ fts_options |= (flags & FTW_MOUNT) ? FTS_XDEV : 0;
+ } else { /* We must be in FTW mode. Nothing else makes sense. */
+ fts_options = FTS_LOGICAL;
+ }
+
+ /* FTW gets a const char *, but FTS expects a null-term array of them. */
+
+ if (!(paths[0] = (char*) alloca(strlen(dir) + 1))) {
+ errno = ENOMEM; /* This is stack... we probably just died anyway. */
+ return -1;
+ }
+
+ strcpy(paths[0], dir);
+ paths[1] = 0; /* null */
+
+ /* Open the file hierarchy. */
+
+ if (!(hierarchy = fts_open(paths, fts_options, 0))) {
+ if (EACCES == errno) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ /* The main loop. Is it not nifty? Worship the loop. */
+
+ bool first = true;
+ while ((entry = fts_read(hierarchy))) {
+ skip_entry = 0;
+ std::string path_name = entry->fts_path;
+
+ switch (entry->fts_info) {
+
+ case FTS_D:
+ if ((MODE_NFTW != mode) || !(flags & FTW_DEPTH)) {
+ if (first) {
+ path_name = path_name.substr(0, path_name.size() - 1);
+ first = false;
+ }
+ ftw_flag = FTW_D;
+ } else {
+ skip_entry = 1;
+ }
+ break;
+
+ case FTS_DNR:
+ ftw_flag = FTW_DNR;
+ break;
+
+ case FTS_F:
+ ftw_flag = FTW_F;
+ break;
+
+ case FTS_SL:
+ ftw_flag = FTW_SL;
+ break;
+
+ case FTS_NS:
+ ftw_flag = FTW_NS;
+ break;
+
+ /* Values that should only occur in nftw mode */
+
+ case FTS_SLNONE:
+ if (MODE_NFTW == mode) {
+ ftw_flag = FTW_SLN;
+ } else {
+ ftw_flag = FTW_SL;
+ }
+ break;
+
+ case FTS_DP:
+ if ((MODE_NFTW == mode) && (flags & FTW_DEPTH)) {
+ ftw_flag = FTW_D;
+ } else {
+ skip_entry = 1;
+ }
+ break;
+
+ default:
+ /* I'm not sure this is right, but we don't have a valid FTW
+ * type to call with, so cowardice seems the better part of
+ * guessing.
+ */
+
+ skip_entry = 1;
+ }
+
+ if (MODE_FTW == mode) {
+ ftw_func = (__ftw_func_t) func;
+ func_ret = (*ftw_func)
+ (path_name.c_str(), entry->fts_statp, ftw_flag);
+ } else if (MODE_NFTW == mode) {
+ ftw_st.base = (entry->fts_pathlen - entry->fts_namelen);
+ ftw_st.level = entry->fts_level;
+
+ nftw_func = (__nftw_func_t) func;
+ func_ret = (*nftw_func)
+ (path_name.c_str(), entry->fts_statp, ftw_flag, &ftw_st);
+ }
+
+ if (0 != func_ret) {
+ return func_ret;
+ }
+ }
+
+ if (0 != errno) { /* fts_read returned NULL, and set errno - bail */
+ return -1;
+ }
+
+ /* The janitors will be upset if we don't clean up after ourselves. */
+
+ if (0 != fts_close(hierarchy)) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/libs/pbd3/libpbd.pc.in b/libs/pbd3/libpbd.pc.in
new file mode 100644
index 0000000000..14d0208845
--- /dev/null
+++ b/libs/pbd3/libpbd.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/pbd
+
+Name: libpbd
+Version: @VERSION@
+Description: libpbd, a library of useful, generic C++ objects
+Requires:
+Libs: -L${libdir} -lpbd @NON_PKG_LIBS@
+Cflags: -I${includedir} @NON_PKG_CFLAGS@
diff --git a/libs/pbd3/libpbd.spec.in b/libs/pbd3/libpbd.spec.in
new file mode 100644
index 0000000000..d50622d638
--- /dev/null
+++ b/libs/pbd3/libpbd.spec.in
@@ -0,0 +1,70 @@
+Summary: A general purpose programming library
+%define lib_name pbd
+Name: lib%{lib_name}
+Version: @VERSION@
+Release: 2
+Copyright: GPL
+Source: .
+Url: http://www.quasimodo.org
+Vendor: Paul Davis <paul@linuxaudiosystems.com>
+Packager: jfm3 <jfm3@acm.org>
+Group: System Environment/Libraries
+Prefix: %{_prefix}
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+
+This library implements a number of programming utilities used by Paul
+Davis (formerly Paul Barton-Davis, hence the name). It is used in
+some of his Open Source software projects. See
+http://ardour.sf.net/ for examples.
+
+%prep
+%setup -q
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure $ARCH_FLAGS --prefix=%{prefix}
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d -m 755 $RPM_BUILD_ROOT%{prefix}/{{include,lib}/%{lib_name}}
+make install INSTALL="%(which install) -p" prefix=$RPM_BUILD_ROOT%{prefix}
+
+%post
+/sbin/ldconfig
+
+%postun
+/sbin/ldconfig
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README AUTHORS NEWS COPYING*
+%{prefix}/lib/libpbd.so*
+
+%package devel
+Summary: A general purpose programming library -- developer version.
+Group: System Environment/Libraries
+
+%description devel
+
+This library implements a number of programming utilities used by Paul
+Davis (formerly Paul Barton-Davis, hence the name). It is used in
+some of his Open Source software projects. See
+http://ardour.sf.net/ for examples.
+
+This package holds static libraries and headers needed by developers
+who wish to use libpbd in their programs.
+
+%files devel
+%defattr(-,root,root)
+%{prefix}/include/pbd/*
+%{prefix}/lib/libpbd.a
+%{prefix}/lib/libpbd.la
+%{prefix}/bin/pbd-config
+%{prefix}/share/aclocal/pbd.m4
+%{prefix}/share/aclocal/unique_args.m4
+
diff --git a/libs/pbd3/mountpoint.cc b/libs/pbd3/mountpoint.cc
new file mode 100644
index 0000000000..160f5e921c
--- /dev/null
+++ b/libs/pbd3/mountpoint.cc
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdio>
+#include <string>
+#include <limits.h>
+
+#include <pbd/mountpoint.h>
+
+using std::string;
+
+#if HAVE_GETMNTENT
+#include <mntent.h>
+
+struct mntent_sorter {
+ bool operator() (const mntent *a, const mntent *b) {
+ return strcmp (a->mnt_dir, b->mnt_dir);
+ }
+};
+
+string
+mountpoint (string path)
+{
+ FILE *mntf;
+ mntent *mnt;
+ unsigned int maxmatch = 0;
+ unsigned int matchlen;
+ const char *cpath = path.c_str();
+ char best[PATH_MAX+1];
+
+ if ((mntf = setmntent ("/etc/mtab", "r")) == 0) {
+ return "";
+ }
+
+ best[0] = '\0';
+
+ while ((mnt = getmntent (mntf))) {
+ unsigned int n;
+
+ n = 0;
+ matchlen = 0;
+
+ /* note: strcmp's semantics are not
+ strict enough to use for this.
+ */
+
+ while (cpath[n] && mnt->mnt_dir[n]) {
+ if (cpath[n] != mnt->mnt_dir[n]) {
+ break;
+ }
+ matchlen++;
+ n++;
+ }
+
+ if (cpath[matchlen] == '\0') {
+
+ endmntent (mntf);
+ return mnt->mnt_dir;
+
+ } else {
+
+ if (matchlen > maxmatch) {
+ snprintf (best, sizeof(best), "%s", mnt->mnt_dir);
+ maxmatch = matchlen;
+ }
+ }
+ }
+
+ endmntent (mntf);
+
+ return best;
+}
+
+#else // no getmntent()
+
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+
+string
+mountpoint (string path)
+{
+//XXX IMPLEMENT ME using getmntinfo() or getfsstat().
+ return "/";
+}
+#endif
+
+#ifdef TEST_MOUNTPOINT
+
+main (int argc, char *argv[])
+{
+ printf ("mp of %s = %s\n", argv[1], mountpoint (argv[1]).c_str());
+ exit (0);
+}
+
+#endif
diff --git a/libs/pbd3/pathscanner.cc b/libs/pbd3/pathscanner.cc
new file mode 100644
index 0000000000..5b96284a90
--- /dev/null
+++ b/libs/pbd3/pathscanner.cc
@@ -0,0 +1,201 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cstdio>
+#include <vector>
+#include <dirent.h>
+
+#include <pbd/error.h>
+#include <pbd/pathscanner.h>
+#include <pbd/stl_delete.h>
+
+vector<string *> *
+PathScanner::operator() (const string &dirpath, const string &regexp,
+ bool match_fullpath, bool return_fullpath,
+ long limit)
+
+{
+ int err;
+ char msg[256];
+
+ if ((err = regcomp (&compiled_pattern, regexp.c_str(),
+ REG_EXTENDED|REG_NOSUB))) {
+
+ regerror (err, &compiled_pattern,
+ msg, sizeof (msg));
+
+ error << "Cannot compile soundfile regexp for use ("
+ << msg
+ << ")"
+ << endmsg;
+
+ return 0;
+ }
+
+ return run_scan (dirpath, &PathScanner::regexp_filter,
+ (bool (*)(const string &, void *)) 0,
+ 0,
+ match_fullpath,
+ return_fullpath,
+ limit);
+}
+
+vector<string *> *
+PathScanner::run_scan (const string &dirpath,
+ bool (PathScanner::*memberfilter)(const string &),
+ bool (*filter)(const string &, void *),
+ void *arg,
+ bool match_fullpath, bool return_fullpath,
+ long limit)
+
+{
+ vector<string *> *result = 0;
+ DIR *dir;
+ struct dirent *finfo;
+ char *pathcopy = strdup (dirpath.c_str());
+ char *thisdir;
+ char fullpath[PATH_MAX+1];
+ string search_str;
+ string *newstr;
+ long nfound = 0;
+
+ if ((thisdir = strtok (pathcopy, ":")) == 0 ||
+ strlen (thisdir) == 0) {
+ free (pathcopy);
+ return 0;
+ }
+
+ result = new vector<string *>;
+
+ do {
+
+ if ((dir = opendir (thisdir)) == 0) {
+ continue;
+ }
+
+ while ((finfo = readdir (dir)) != 0) {
+
+ snprintf (fullpath, sizeof(fullpath), "%s/%s",
+ thisdir, finfo->d_name);
+
+ if (match_fullpath) {
+ search_str = fullpath;
+ } else {
+ search_str = finfo->d_name;
+ }
+
+ /* handle either type of function ptr */
+
+ if (memberfilter) {
+ if (!(this->*memberfilter)(search_str)) {
+ continue;
+ }
+ } else {
+ if (!filter(search_str, arg)) {
+ continue;
+ }
+ }
+
+ if (return_fullpath) {
+ newstr = new string (fullpath);
+ } else {
+ newstr = new string (finfo->d_name);
+ }
+
+ result->push_back (newstr);
+ nfound++;
+ }
+
+ closedir (dir);
+
+ } while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":")));
+
+ free (pathcopy);
+ return result;
+}
+
+string *
+PathScanner::find_first (const string &dirpath,
+ const string &regexp,
+ bool match_fullpath,
+ bool return_fullpath)
+{
+ vector<string *> *res;
+ string *ret;
+ int err;
+ char msg[256];
+
+ if ((err = regcomp (&compiled_pattern, regexp.c_str(),
+ REG_EXTENDED|REG_NOSUB))) {
+
+ regerror (err, &compiled_pattern,
+ msg, sizeof (msg));
+
+ error << "Cannot compile soundfile regexp for use (" << msg << ")" << endmsg;
+
+
+ return 0;
+ }
+
+ res = run_scan (dirpath,
+ &PathScanner::regexp_filter,
+ (bool (*)(const string &, void *)) 0,
+ 0,
+ match_fullpath,
+ return_fullpath,
+ 1);
+
+ if (res->size() == 0) {
+ ret = 0;
+ } else {
+ ret = res->front();
+ }
+ vector_delete (res);
+ delete res;
+ return ret;
+}
+
+string *
+PathScanner::find_first (const string &dirpath,
+ bool (*filter)(const string &, void *),
+ void *arg,
+ bool match_fullpath,
+ bool return_fullpath)
+{
+ vector<string *> *res;
+ string *ret;
+
+ res = run_scan (dirpath,
+ (bool (PathScanner::*)(const string &)) 0,
+ filter,
+ 0,
+ match_fullpath,
+ return_fullpath, 1);
+
+ if (res->size() == 0) {
+ ret = 0;
+ } else {
+ ret = res->front();
+ }
+ vector_delete (res);
+ delete res;
+ return ret;
+}
diff --git a/libs/pbd3/pbd-config.in b/libs/pbd3/pbd-config.in
new file mode 100644
index 0000000000..4c53125b59
--- /dev/null
+++ b/libs/pbd3/pbd-config.in
@@ -0,0 +1,232 @@
+#!/bin/sh
+
+af_libs=
+af_cflags=
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+
+
+##
+## Define usage()
+##
+usage()
+{
+ cat <<EOF
+Usage: pbd-config [OPTIONS] [LIBRARIES]
+Options:
+ --cflags print pre-processor and compiler flags
+ --libs print library linking information
+ --libs-dirs only print the -L/-R part of --libs
+ --libs-names only print the -l part of --libs
+ --help display this help and exit
+ --macros print the path to m4 macros
+
+ --prefix[=DIR]
+ --exec_prefix[=DIR]
+ --version output pbd version information
+Libraries:
+ pbd
+EOF
+ exit $1
+}
+
+##
+## Process options
+##
+parse()
+{
+# we must be called with at least one argument
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+# at least one option should be selected
+case "$1" in
+ --*)
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+esac
+
+# grab all -- arguments
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) af_optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) af_optarg= ;;
+ esac
+
+ case $1 in
+ --help)
+ usage 0 0>&2
+ ;;
+ --cflags)
+ af_echo_cflags=yes
+ ;;
+ --libs)
+ af_echo_libs_L=yes
+ af_echo_libs_l=yes
+ ;;
+ --libs-dirs)
+ af_echo_libs_L=yes
+ ;;
+ --libs-names)
+ af_echo_libs_l=yes
+ ;;
+ --macros*)
+
+echo -I @prefix@/include/pbd/macros
+exit
+
+ ;;
+ --prefix=*)
+ prefix=$af_optarg
+ af_prefix_set=yes
+ ;;
+ --prefix)
+ af_echo_prefix=yes
+ ;;
+ --exec_prefix=*)
+ exec_prefix=$af_optarg
+ af_exec_prefix_set=yes
+ ;;
+ --exec_prefix)
+ af_echo_exec_prefix=yes
+ ;;
+ --version)
+ af_echo_version=yes
+ ;;
+ --*)
+ usage 1 1>&2
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+# if we have a default library use it
+if test $# -eq 0; then
+if test "X$af_lib_default" != "X"; then
+ af_lib__AF_LIB_DEFAULT=yes
+ return
+fi
+fi
+
+while test $# -gt 0; do
+ case $1 in
+ pbd)
+ af_lib_pbd=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+}
+
+print_result()
+{
+if test "X$af_echo_cflags" = "Xyes"; then
+ af_all_flags="$af_cflags"
+fi
+
+if test "X$af_echo_libs_L" = "Xyes" || test "X$af_echo_libs_l" = "Xyes"; then
+ af_all_flags="$af_all_flags $af_libs"
+fi
+
+if test -z "$af_all_flags" || test "X$af_all_flags" = "X "; then
+ exit 1
+fi
+
+# Straight out any possible duplicates, but be careful to
+# get `-lfoo -lbar -lbaz' for `-lfoo -lbaz -lbar -lbaz'
+af_other_flags=
+af_lib_L_flags=
+af_rev_libs=
+for i in $af_all_flags; do
+ case "$i" in
+ # a library, save it for later, in reverse order
+ -l*) af_rev_libs="$i $af_rev_libs" ;;
+ -L*|-R*)
+ if test "X$af_echo_libs_L" = "Xyes"; then
+ case " $af_lib_L_flags " in
+ *\ $i\ *) ;; # already there
+ *) af_lib_L_flags="$af_lib_L_flags $i" ;; # add it to output
+ esac
+ fi;;
+ *)
+ case " $af_other_flags " in
+ *\ $i\ *) ;; # already there
+ *) af_other_flags="$af_other_flags $i" ;; # add it to output
+ esac ;;
+ esac
+done
+
+af_ord_libs=
+if test "X$af_echo_libs_l" = "Xyes"; then
+ for i in $af_rev_libs; do
+ case " $af_ord_libs " in
+ *\ $i\ *) ;; # already there
+ *) af_ord_libs="$i $af_ord_libs" ;; # add it to output in reverse order
+ esac
+ done
+fi
+
+echo $af_other_flags $af_lib_L_flags $af_ord_libs
+}
+
+##
+## Main Body
+##
+
+parse $*
+
+
+##
+## Initialize names
+##
+
+
+
+
+
+if test "X$af_echo_prefix" = "Xyes"; then
+ echo $prefix
+fi
+
+if test "X$af_echo_exec_prefix" = "Xyes"; then
+ echo $exec_prefix
+fi
+
+if test "X$af_echo_version" = "Xyes"; then
+ echo @LIBPBD_VERSION@
+ exit 0
+fi
+
+
+##
+## Libraries
+##
+
+#dummy because this should always be selected
+
+
+if test "@includedir@" != /usr/include ; then
+ includes="-I@includedir@"
+fi
+if test "@libdir@" != /usr/lib ; then
+ libs="-L@libdir@"
+fi
+af_cflags="$af_cflags $includes @SIGC_CFLAGS@"
+af_libs="$libs -lpbd @PBD_LIBS@ $af_libs"
+
+
+
+
+print_result
+
+exit 0
+
diff --git a/libs/pbd3/pbd/.DS_Store b/libs/pbd3/pbd/.DS_Store
new file mode 100644
index 0000000000..5008ddfcf5
--- /dev/null
+++ b/libs/pbd3/pbd/.DS_Store
Binary files differ
diff --git a/libs/pbd3/pbd/.cvsignore b/libs/pbd3/pbd/.cvsignore
new file mode 100644
index 0000000000..67020331ba
--- /dev/null
+++ b/libs/pbd3/pbd/.cvsignore
@@ -0,0 +1 @@
+version.h
diff --git a/libs/pbd3/pbd/abstract_ui.h b/libs/pbd3/pbd/abstract_ui.h
new file mode 100644
index 0000000000..0c845c15cd
--- /dev/null
+++ b/libs/pbd3/pbd/abstract_ui.h
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_abstract_ui_h__
+#define __pbd_abstract_ui_h__
+
+#include <pbd/receiver.h>
+#include <sigc++/sigc++.h>
+
+class Touchable;
+
+class AbstractUI : public Receiver
+{
+ public:
+ enum RequestType {
+ ErrorMessage,
+ Quit,
+ CallSlot,
+ CallSlotLocked,
+ TouchDisplay,
+ StateChange,
+ SetTip,
+ AddIdle,
+ AddTimeout,
+ };
+
+ bool ok() { return _ok; }
+
+ AbstractUI () {}
+ virtual ~AbstractUI() {}
+
+ virtual void run (Receiver &old_receiver) = 0;
+ virtual void quit () = 0;
+ virtual bool running () = 0;
+ virtual void request (RequestType) = 0;
+ virtual void touch_display (Touchable *) = 0;
+ virtual void call_slot (sigc::slot<void>) = 0;
+ virtual bool caller_is_gui_thread() = 0;
+
+ /* needed to be a receiver ... */
+
+ virtual void receive (Transmitter::Channel, const char *) = 0;
+
+ protected:
+ bool _ok;
+};
+
+#endif // __pbd_abstract_ui_h__
+
+
diff --git a/libs/pbd3/pbd/atomic.h b/libs/pbd3/pbd/atomic.h
new file mode 100644
index 0000000000..81e76f41fa
--- /dev/null
+++ b/libs/pbd3/pbd/atomic.h
@@ -0,0 +1,1232 @@
+/*
+ Copyright (C) 2001 Paul Davis and others (see below)
+ Code derived from various headers from the Linux kernel.
+ Copyright attributions maintained where present.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __libpbd_atomic_h__
+#define __libpbd_atomic_h__
+
+#ifdef HAVE_SMP /* a macro we control, to manage ... */
+#define CONFIG_SMP /* ... the macro the kernel headers use */
+#endif
+
+#if defined(__powerpc__) || defined(__ppc__)
+
+/*
+ * BK Id: SCCS/s.atomic.h 1.15 10/28/01 10:37:22 trini
+ */
+/*
+ * PowerPC atomic operations
+ */
+
+#ifndef _ASM_PPC_ATOMIC_H_
+#define _ASM_PPC_ATOMIC_H_
+
+typedef struct { volatile int counter; } atomic_t;
+
+
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
+extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
+
+#ifdef CONFIG_SMP
+#define SMP_ISYNC "\n\tisync"
+#else
+#define SMP_ISYNC
+#endif
+
+static __inline__ void atomic_add(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%3\n\
+ add %0,%2,%0\n\
+ stwcx. %0,0,%3\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (a), "r" (&v->counter), "m" (v->counter)
+ : "cc");
+}
+
+static __inline__ int atomic_add_return(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%2\n\
+ add %0,%1,%0\n\
+ stwcx. %0,0,%2\n\
+ bne- 1b"
+ SMP_ISYNC
+ : "=&r" (t)
+ : "r" (a), "r" (&v->counter)
+ : "cc", "memory");
+
+ return t;
+}
+
+static __inline__ void atomic_sub(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%3\n\
+ subf %0,%2,%0\n\
+ stwcx. %0,0,%3\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (a), "r" (&v->counter), "m" (v->counter)
+ : "cc");
+}
+
+static __inline__ int atomic_sub_return(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%2\n\
+ subf %0,%1,%0\n\
+ stwcx. %0,0,%2\n\
+ bne- 1b"
+ SMP_ISYNC
+ : "=&r" (t)
+ : "r" (a), "r" (&v->counter)
+ : "cc", "memory");
+
+ return t;
+}
+
+static __inline__ void atomic_inc(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%2\n\
+ addic %0,%0,1\n\
+ stwcx. %0,0,%2\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (&v->counter), "m" (v->counter)
+ : "cc");
+}
+
+static __inline__ int atomic_inc_return(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%1\n\
+ addic %0,%0,1\n\
+ stwcx. %0,0,%1\n\
+ bne- 1b"
+ SMP_ISYNC
+ : "=&r" (t)
+ : "r" (&v->counter)
+ : "cc", "memory");
+
+ return t;
+}
+
+static __inline__ void atomic_dec(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%2\n\
+ addic %0,%0,-1\n\
+ stwcx. %0,0,%2\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (&v->counter), "m" (v->counter)
+ : "cc");
+}
+
+static __inline__ int atomic_dec_return(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%1\n\
+ addic %0,%0,-1\n\
+ stwcx. %0,0,%1\n\
+ bne- 1b"
+ SMP_ISYNC
+ : "=&r" (t)
+ : "r" (&v->counter)
+ : "cc", "memory");
+
+ return t;
+}
+
+#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
+
+/*
+ * Atomically test *v and decrement if it is greater than 0.
+ * The function returns the old value of *v minus 1.
+ */
+static __inline__ int atomic_dec_if_positive(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__(
+"1: lwarx %0,0,%1\n\
+ addic. %0,%0,-1\n\
+ blt- 2f\n\
+ stwcx. %0,0,%1\n\
+ bne- 1b"
+ SMP_ISYNC
+ "\n\
+2:" : "=&r" (t)
+ : "r" (&v->counter)
+ : "cc", "memory");
+
+ return t;
+}
+
+#define smp_mb__before_atomic_dec() smp_mb()
+#define smp_mb__after_atomic_dec() smp_mb()
+#define smp_mb__before_atomic_inc() smp_mb()
+#define smp_mb__after_atomic_inc() smp_mb()
+
+#endif /* _ASM_PPC_ATOMIC_H_ */
+
+/***********************************************************************/
+
+# else /* !PPC */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#ifndef __ARCH_I386_ATOMIC__
+#define __ARCH_I386_ATOMIC__
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ */
+
+#ifdef CONFIG_SMP
+#define SMP_LOCK "lock ; "
+#else
+#define SMP_LOCK ""
+#endif
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_read(v) ((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v. Note that the guaranteed useful range
+ * of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_add(int i, atomic_t *v)
+{
+ __asm__ __volatile__(
+ SMP_LOCK "addl %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_sub(int i, atomic_t *v)
+{
+ __asm__ __volatile__(
+ SMP_LOCK "subl %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ SMP_LOCK "subl %2,%0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"ir" (i), "m" (v->counter) : "memory");
+ return c;
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_inc(atomic_t *v)
+{
+ __asm__ __volatile__(
+ SMP_LOCK "incl %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+}
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_dec(atomic_t *v)
+{
+ __asm__ __volatile__(
+ SMP_LOCK "decl %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+}
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_dec_and_test(atomic_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ SMP_LOCK "decl %0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"m" (v->counter) : "memory");
+ return c != 0;
+}
+
+/**
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_inc_and_test(atomic_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ SMP_LOCK "incl %0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"m" (v->counter) : "memory");
+ return c != 0;
+}
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_add_negative(int i, atomic_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__(
+ SMP_LOCK "addl %2,%0; sets %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"ir" (i), "m" (v->counter) : "memory");
+ return c;
+}
+
+/* These are x86-specific, used by some header files */
+#define atomic_clear_mask(mask, addr) \
+__asm__ __volatile__(SMP_LOCK "andl %0,%1" \
+: : "r" (~(mask)),"m" (*addr) : "memory")
+
+#define atomic_set_mask(mask, addr) \
+__asm__ __volatile__(SMP_LOCK "orl %0,%1" \
+: : "r" (mask),"m" (*addr) : "memory")
+
+/* Atomic operations are already serializing on x86 */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#endif /* __ARCH_I386_ATOMIC__ */
+
+/***********************************************************************/
+
+#else /* !PPC && !i386 */
+
+#ifdef __sparc__
+
+/* atomic.h: These still suck, but the I-cache hit rate is higher.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ */
+
+#ifndef __ARCH_SPARC_ATOMIC__
+#define __ARCH_SPARC_ATOMIC__
+
+typedef struct { volatile int counter; } atomic_t;
+
+#ifndef CONFIG_SMP
+
+#define ATOMIC_INIT(i) { (i) }
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v, i) (((v)->counter) = i)
+
+#else
+/* We do the bulk of the actual work out of line in two common
+ * routines in assembler, see arch/sparc/lib/atomic.S for the
+ * "fun" details.
+ *
+ * For SMP the trick is you embed the spin lock byte within
+ * the word, use the low byte so signedness is easily retained
+ * via a quick arithmetic shift. It looks like this:
+ *
+ * ----------------------------------------
+ * | signed 24-bit counter value | lock | atomic_t
+ * ----------------------------------------
+ * 31 8 7 0
+ */
+
+#define ATOMIC_INIT(i) { (i << 8) }
+
+static __inline__ int atomic_read(atomic_t *v)
+{
+ int ret = v->counter;
+
+ while(ret & 0xff)
+ ret = v->counter;
+
+ return ret >> 8;
+}
+
+#define atomic_set(v, i) (((v)->counter) = ((i) << 8))
+#endif
+
+static __inline__ int __atomic_add(int i, atomic_t *v)
+{
+ register volatile int *ptr asm("g1");
+ register int increment asm("g2");
+
+ ptr = &v->counter;
+ increment = i;
+
+ __asm__ __volatile__(
+ "mov %%o7, %%g4\n\t"
+ "call ___atomic_add\n\t"
+ " add %%o7, 8, %%o7\n"
+ : "=&r" (increment)
+ : "0" (increment), "r" (ptr)
+ : "g3", "g4", "g7", "memory", "cc");
+
+ return increment;
+}
+
+static __inline__ int __atomic_sub(int i, atomic_t *v)
+{
+ register volatile int *ptr asm("g1");
+ register int increment asm("g2");
+
+ ptr = &v->counter;
+ increment = i;
+
+ __asm__ __volatile__(
+ "mov %%o7, %%g4\n\t"
+ "call ___atomic_sub\n\t"
+ " add %%o7, 8, %%o7\n"
+ : "=&r" (increment)
+ : "0" (increment), "r" (ptr)
+ : "g3", "g4", "g7", "memory", "cc");
+
+ return increment;
+}
+
+#define atomic_add(i, v) ((void)__atomic_add((i), (v)))
+#define atomic_sub(i, v) ((void)__atomic_sub((i), (v)))
+
+#define atomic_dec_return(v) __atomic_sub(1, (v))
+#define atomic_inc_return(v) __atomic_add(1, (v))
+
+#define atomic_sub_and_test(i, v) (__atomic_sub((i), (v)) == 0)
+#define atomic_dec_and_test(v) (__atomic_sub(1, (v)) == 0)
+
+#define atomic_inc(v) ((void)__atomic_add(1, (v)))
+#define atomic_dec(v) ((void)__atomic_sub(1, (v)))
+
+#define atomic_add_negative(i, v) (__atomic_add((i), (v)) < 0)
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+
+#endif /* !(__ARCH_SPARC_ATOMIC__) */
+
+/***********************************************************************/
+
+#else
+
+#ifdef __ia64__
+
+#ifndef __ARCH_IA64_ATOMIC__
+#define __ARCH_IA64_ATOMIC__
+
+typedef volatile int atomic_t;
+
+inline
+int
+atomic_read (const atomic_t * a)
+{
+ return *a;
+}
+
+inline
+void
+atomic_set(atomic_t *a, int v)
+{
+ *a = v;
+}
+
+inline
+void
+atomic_inc (atomic_t *v)
+{
+ int old, r;
+
+ do {
+ old = atomic_read(v);
+ __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old));
+ __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv"
+ : "=r"(r) : "r"(v), "r"(old + 1)
+ : "memory");
+ } while (r != old);
+}
+
+inline
+void
+atomic_dec (atomic_t *v)
+{
+ int old, r;
+
+ do {
+ old = atomic_read(v);
+ __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old));
+ __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv"
+ : "=r"(r) : "r"(v), "r"(old - 1)
+ : "memory");
+ } while (r != old);
+}
+
+inline
+int
+atomic_dec_and_test (atomic_t *v)
+{
+ int old, r;
+
+ do {
+ old = atomic_read(v);
+ __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old));
+ __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv"
+ : "=r"(r) : "r"(v), "r"(old - 1)
+ : "memory");
+ } while (r != old);
+ return old != 1;
+}
+
+#endif /* !(__ARCH_IA64_ATOMIC__) */
+
+#else
+
+#ifdef __alpha__
+
+#ifndef _ALPHA_ATOMIC_H
+#define _ALPHA_ATOMIC_H
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc...
+ *
+ * But use these as seldom as possible since they are much slower
+ * than regular operations.
+ */
+
+
+/*
+ * Counter is volatile to make sure gcc doesn't try to be clever
+ * and move things around on us. We need to use _exactly_ the address
+ * the user gave us, not some alias that contains the same information.
+ */
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) ((v)->counter = (i))
+
+/*
+ * To get proper branch prediction for the main line, we must branch
+ * forward to code at the end of this object's .text section, then
+ * branch back to restart the operation.
+ */
+
+static __inline__ void atomic_add(int i, atomic_t * v)
+{
+ unsigned long temp;
+ __asm__ __volatile__(
+ "1: ldl_l %0,%1\n"
+ " addl %0,%2,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,2f\n"
+ ".subsection 2\n"
+ "2: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (v->counter)
+ :"Ir" (i), "m" (v->counter));
+}
+
+static __inline__ void atomic_sub(int i, atomic_t * v)
+{
+ unsigned long temp;
+ __asm__ __volatile__(
+ "1: ldl_l %0,%1\n"
+ " subl %0,%2,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,2f\n"
+ ".subsection 2\n"
+ "2: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (v->counter)
+ :"Ir" (i), "m" (v->counter));
+}
+
+/*
+ * Same as above, but return the result value
+ */
+static __inline__ long atomic_add_return(int i, atomic_t * v)
+{
+ long temp, result;
+ __asm__ __volatile__(
+ "1: ldl_l %0,%1\n"
+ " addl %0,%3,%2\n"
+ " addl %0,%3,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,2f\n"
+ " mb\n"
+ ".subsection 2\n"
+ "2: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (v->counter), "=&r" (result)
+ :"Ir" (i), "m" (v->counter) : "memory");
+ return result;
+}
+
+static __inline__ long atomic_sub_return(int i, atomic_t * v)
+{
+ long temp, result;
+ __asm__ __volatile__(
+ "1: ldl_l %0,%1\n"
+ " subl %0,%3,%2\n"
+ " subl %0,%3,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,2f\n"
+ " mb\n"
+ ".subsection 2\n"
+ "2: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (v->counter), "=&r" (result)
+ :"Ir" (i), "m" (v->counter) : "memory");
+ return result;
+}
+
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+#define atomic_inc(v) atomic_add(1,(v))
+#define atomic_dec(v) atomic_sub(1,(v))
+
+#define smp_mb__before_atomic_dec() smp_mb()
+#define smp_mb__after_atomic_dec() smp_mb()
+#define smp_mb__before_atomic_inc() smp_mb()
+#define smp_mb__after_atomic_inc() smp_mb()
+
+#endif /* _ALPHA_ATOMIC_H */
+
+#else
+
+#ifdef __s390__
+
+#ifndef __ARCH_S390_ATOMIC__
+#define __ARCH_S390_ATOMIC__
+
+/*
+ * include/asm-s390/atomic.h
+ *
+ * S390 version
+ * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ * Denis Joseph Barrow
+ *
+ * Derived from "include/asm-i386/bitops.h"
+ * Copyright (C) 1992, Linus Torvalds
+ *
+ */
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ * S390 uses 'Compare And Swap' for atomicity in SMP enviroment
+ */
+
+typedef struct { volatile int counter; } __attribute__ ((aligned (4))) atomic_t;
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_eieio() __asm__ __volatile__ ("BCR 15,0")
+
+#define __CS_LOOP(old_val, new_val, ptr, op_val, op_string) \
+ __asm__ __volatile__(" l %0,0(%2)\n" \
+ "0: lr %1,%0\n" \
+ op_string " %1,%3\n" \
+ " cs %0,%1,0(%2)\n" \
+ " jl 0b" \
+ : "=&d" (old_val), "=&d" (new_val) \
+ : "a" (ptr), "d" (op_val) : "cc" );
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+static __inline__ void atomic_add(int i, atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, i, "ar");
+}
+
+static __inline__ int atomic_add_return (int i, atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, i, "ar");
+ return new_val;
+}
+
+static __inline__ int atomic_add_negative(int i, atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, i, "ar");
+ return new_val < 0;
+}
+
+static __inline__ void atomic_sub(int i, atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, i, "sr");
+}
+
+static __inline__ void atomic_inc(volatile atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, 1, "ar");
+}
+
+static __inline__ int atomic_inc_return(volatile atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, 1, "ar");
+ return new_val;
+}
+
+static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, 1, "ar");
+ return new_val != 0;
+}
+
+static __inline__ void atomic_dec(volatile atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, 1, "sr");
+}
+
+static __inline__ int atomic_dec_return(volatile atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, 1, "sr");
+ return new_val;
+}
+
+static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, 1, "sr");
+ return new_val == 0;
+}
+
+static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, ~mask, "nr");
+}
+
+static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v)
+{
+ int old_val, new_val;
+ __CS_LOOP(old_val, new_val, v, mask, "or");
+}
+
+/*
+ returns 0 if expected_oldval==value in *v ( swap was successful )
+ returns 1 if unsuccessful.
+*/
+static __inline__ int
+atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)
+{
+ int retval;
+
+ __asm__ __volatile__(
+ " lr 0,%2\n"
+ " cs 0,%3,0(%1)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ "0:"
+ : "=&d" (retval)
+ : "a" (v), "d" (expected_oldval) , "d" (new_val)
+ : "0", "cc");
+ return retval;
+}
+
+/*
+ Spin till *v = expected_oldval then swap with newval.
+ */
+static __inline__ void
+atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v)
+{
+ __asm__ __volatile__(
+ "0: lr 0,%1\n"
+ " cs 0,%2,0(%0)\n"
+ " jl 0b\n"
+ : : "a" (v), "d" (expected_oldval) , "d" (new_val)
+ : "cc", "0" );
+}
+
+#define smp_mb__before_atomic_dec() smp_mb()
+#define smp_mb__after_atomic_dec() smp_mb()
+#define smp_mb__before_atomic_inc() smp_mb()
+#define smp_mb__after_atomic_inc() smp_mb()
+
+#endif /* __ARCH_S390_ATOMIC __ */
+
+#else
+
+#ifdef __mips__
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ *
+ * But use these as seldom as possible since they are much more slower
+ * than regular operations.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997, 2000 by Ralf Baechle
+ */
+#ifndef __ASM_ATOMIC_H
+#define __ASM_ATOMIC_H
+
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+/*
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_read(v) ((v)->counter)
+
+/*
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_set(v,i) ((v)->counter = (i))
+
+/*
+ * ... while for MIPS II and better we can use ll/sc instruction. This
+ * implementation is SMP safe ...
+ */
+
+/*
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v. Note that the guaranteed useful range
+ * of an atomic_t is only 24 bits.
+ */
+extern __inline__ void atomic_add(int i, atomic_t * v)
+{
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ ".set push # atomic_add\n"
+ ".set mips2 \n"
+ "1: ll %0, %1 \n"
+ " addu %0, %2 \n"
+ " sc %0, %1 \n"
+ " beqz %0, 1b \n"
+ ".set pop \n"
+ : "=&r" (temp), "=m" (v->counter)
+ : "Ir" (i), "m" (v->counter));
+}
+
+/*
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+extern __inline__ void atomic_sub(int i, atomic_t * v)
+{
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ ".set push # atomic_sub\n"
+ ".set mips2 \n"
+ "1: ll %0, %1 \n"
+ " subu %0, %2 \n"
+ " sc %0, %1 \n"
+ " beqz %0, 1b \n"
+ ".set pop \n"
+ : "=&r" (temp), "=m" (v->counter)
+ : "Ir" (i), "m" (v->counter));
+}
+
+/*
+ * Same as above, but return the result value
+ */
+extern __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+ unsigned long temp, result;
+
+ __asm__ __volatile__(
+ ".set push # atomic_add_return\n"
+ ".set mips2 \n"
+ ".set noreorder \n"
+ "1: ll %1, %2 \n"
+ " addu %0, %1, %3 \n"
+ " sc %0, %2 \n"
+ " beqz %0, 1b \n"
+ " addu %0, %1, %3 \n"
+ " sync \n"
+ ".set pop \n"
+ : "=&r" (result), "=&r" (temp), "=m" (v->counter)
+ : "Ir" (i), "m" (v->counter)
+ : "memory");
+
+ return result;
+}
+
+extern __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+ unsigned long temp, result;
+
+ __asm__ __volatile__(
+ ".set push # atomic_sub_return\n"
+ ".set mips2 \n"
+ ".set noreorder \n"
+ "1: ll %1, %2 \n"
+ " subu %0, %1, %3 \n"
+ " sc %0, %2 \n"
+ " beqz %0, 1b \n"
+ " subu %0, %1, %3 \n"
+ " sync \n"
+ ".set pop \n"
+ : "=&r" (result), "=&r" (temp), "=m" (v->counter)
+ : "Ir" (i), "m" (v->counter)
+ : "memory");
+
+ return result;
+}
+
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+/*
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0)
+
+/*
+ * atomic_dec_and_test - decrement by 1 and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+/*
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_inc(v) atomic_add(1,(v))
+
+/*
+ * atomic_dec - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_dec(v) atomic_sub(1,(v))
+
+/*
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ *
+ * Currently not implemented for MIPS.
+ */
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec() smp_mb()
+#define smp_mb__after_atomic_dec() smp_mb()
+#define smp_mb__before_atomic_inc() smp_mb()
+#define smp_mb__after_atomic_inc() smp_mb()
+
+#endif /* __ASM_ATOMIC_H */
+
+#else
+
+#if defined(__m68k__)
+
+#ifndef __ARCH_M68K_ATOMIC__
+#define __ARCH_M68K_ATOMIC__
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ */
+
+/*
+ * We do not have SMP m68k systems, so we don't have to deal with that.
+ */
+
+typedef struct { int counter; } atomic_t;
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v, i) (((v)->counter) = i)
+
+static __inline__ void atomic_add(int i, atomic_t *v)
+{
+ __asm__ __volatile__("addl %1,%0" : "=m" (*v) : "id" (i), "0" (*v));
+}
+
+static __inline__ void atomic_sub(int i, atomic_t *v)
+{
+ __asm__ __volatile__("subl %1,%0" : "=m" (*v) : "id" (i), "0" (*v));
+}
+
+static __inline__ void atomic_inc(volatile atomic_t *v)
+{
+ __asm__ __volatile__("addql #1,%0" : "=m" (*v): "0" (*v));
+}
+
+static __inline__ void atomic_dec(volatile atomic_t *v)
+{
+ __asm__ __volatile__("subql #1,%0" : "=m" (*v): "0" (*v));
+}
+
+static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
+{
+ char c;
+ __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "=m" (*v): "1" (*v));
+ return c != 0;
+}
+
+#define atomic_clear_mask(mask, v) \
+ __asm__ __volatile__("andl %1,%0" : "=m" (*v) : "id" (~(mask)),"0"(*v))
+
+#define atomic_set_mask(mask, v) \
+ __asm__ __volatile__("orl %1,%0" : "=m" (*v) : "id" (mask),"0"(*v))
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#endif /* __ARCH_M68K_ATOMIC __ */
+
+#else
+
+#warning libs/pbd has no implementation of strictly atomic operations for your hardware.
+
+#define __NO_STRICT_ATOMIC
+#ifdef __NO_STRICT_ATOMIC
+
+/*
+ * Because the implementations from the kernel (where all these come
+ * from) use cli and spinlocks for hppa and arm...
+ */
+
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) ((v)->counter = (i))
+
+static __inline__ void atomic_inc(atomic_t *v)
+{
+ v->counter++;
+}
+
+static __inline__ void atomic_dec(atomic_t *v)
+{
+ v->counter--;
+}
+
+static __inline__ int atomic_dec_and_test(atomic_t *v)
+{
+ int res;
+ v->counter--;
+ res = v->counter;
+ return res == 0;
+}
+
+static __inline__ int atomic_inc_and_test(atomic_t *v)
+{
+ int res;
+ v->counter++;
+ res = v->counter;
+ return res == 0;
+}
+
+# endif /* __NO_STRICT_ATOMIC */
+# endif /* m68k */
+# endif /* mips */
+# endif /* s390 */
+# endif /* alpha */
+# endif /* ia64 */
+# endif /* sparc */
+# endif /* i386 */
+# endif /* ppc */
+
+#endif /* __libpbd_atomic_h__ */
+
diff --git a/libs/pbd3/pbd/basename.h b/libs/pbd3/pbd/basename.h
new file mode 100644
index 0000000000..01f40b6b6a
--- /dev/null
+++ b/libs/pbd3/pbd/basename.h
@@ -0,0 +1,15 @@
+#ifndef __stupid_basename_h__
+#define __stupid_basename_h__
+
+#include <string>
+
+namespace PBD
+{
+
+extern char *basename (const char *);
+extern std::string basename (const std::string);
+extern std::string basename_nosuffix (const std::string);
+
+};
+
+#endif // __stupid_basename_h__
diff --git a/libs/pbd3/pbd/compose.h b/libs/pbd3/pbd/compose.h
new file mode 100644
index 0000000000..9a65a3e0b1
--- /dev/null
+++ b/libs/pbd3/pbd/compose.h
@@ -0,0 +1,393 @@
+/* Defines String::compose(fmt, arg...) for easy, i18n-friendly
+ * composition of strings.
+ *
+ * Version 1.0.
+ *
+ * Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>.
+ *
+ * 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+//
+// Basic usage is like
+//
+// std::cout << String::compose("This is a %1x%2 matrix.", rows, cols);
+//
+// See http://www.cs.auc.dk/~olau/compose/ or the included README.compose for
+// more details.
+//
+
+#ifndef STRING_COMPOSE_H
+#define STRING_COMPOSE_H
+
+#include <sstream>
+#include <string>
+#include <list>
+#include <map> // for multimap
+
+namespace StringPrivate
+{
+ // the actual composition class - using string::compose is cleaner, so we
+ // hide it here
+ class Composition
+ {
+ public:
+ // initialize and prepare format string on the form "text %1 text %2 etc."
+ explicit Composition(std::string fmt);
+
+ // supply an replacement argument starting from %1
+ template <typename T>
+ Composition &arg(const T &obj);
+
+ // compose and return string
+ std::string str() const;
+
+ private:
+ std::ostringstream os;
+ int arg_no;
+
+ // we store the output as a list - when the output string is requested, the
+ // list is concatenated to a string; this way we can keep iterators into
+ // the list instead of into a string where they're possibly invalidated on
+ // inserting a specification string
+ typedef std::list<std::string> output_list;
+ output_list output;
+
+ // the initial parse of the format string fills in the specification map
+ // with positions for each of the various %?s
+ typedef std::multimap<int, output_list::iterator> specification_map;
+ specification_map specs;
+ };
+
+ // helper for converting spec string numbers
+ inline int char_to_int(char c)
+ {
+ switch (c) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ default: return -1000;
+ }
+ }
+
+ inline bool is_number(int n)
+ {
+ switch (n) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+
+ // implementation of class Composition
+ template <typename T>
+ inline Composition &Composition::arg(const T &obj)
+ {
+ os << obj;
+
+ std::string rep = os.str();
+
+ if (!rep.empty()) { // manipulators don't produce output
+ for (specification_map::const_iterator i = specs.lower_bound(arg_no),
+ end = specs.upper_bound(arg_no); i != end; ++i) {
+ output_list::iterator pos = i->second;
+ ++pos;
+
+ output.insert(pos, rep);
+ }
+
+ os.str(std::string());
+ //os.clear();
+ ++arg_no;
+ }
+
+ return *this;
+ }
+
+ inline Composition::Composition(std::string fmt)
+ : arg_no(1)
+ {
+ std::string::size_type b = 0, i = 0;
+
+ // fill in output with the strings between the %1 %2 %3 etc. and
+ // fill in specs with the positions
+ while (i < fmt.length()) {
+ if (fmt[i] == '%' && i + 1 < fmt.length()) {
+ if (fmt[i + 1] == '%') { // catch %%
+ fmt.replace(i, 2, "%");
+ ++i;
+ }
+ else if (is_number(fmt[i + 1])) { // aha! a spec!
+ // save string
+ output.push_back(fmt.substr(b, i - b));
+
+ int n = 1; // number of digits
+ int spec_no = 0;
+
+ do {
+ spec_no += char_to_int(fmt[i + n]);
+ spec_no *= 10;
+ ++n;
+ } while (i + n < fmt.length() && is_number(fmt[i + n]));
+
+ spec_no /= 10;
+ output_list::iterator pos = output.end();
+ --pos; // safe since we have just inserted a string>
+
+ specs.insert(specification_map::value_type(spec_no, pos));
+
+ // jump over spec string
+ i += n;
+ b = i;
+ }
+ else
+ ++i;
+ }
+ else
+ ++i;
+ }
+
+ if (i - b > 0) // add the rest of the string
+ output.push_back(fmt.substr(b, i - b));
+ }
+
+ inline std::string Composition::str() const
+ {
+ // assemble string
+ std::string str;
+
+ for (output_list::const_iterator i = output.begin(), end = output.end();
+ i != end; ++i)
+ str += *i;
+
+ return str;
+ }
+}
+
+// now for the real thing(s)
+//namespace String
+//{
+ // a series of functions which accept a format string on the form "text %1
+ // more %2 less %3" and a number of templated parameters and spits out the
+ // composited string
+ template <typename T1>
+ inline std::string compose(const std::string &fmt, const T1 &o1)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1);
+ return c.str();
+ }
+
+ template <typename T1, typename T2>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8, const T9 &o9)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8, const T9 &o9,
+ const T10 &o10)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+ .arg(o10);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8, const T9 &o9,
+ const T10 &o10, const T11 &o11)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+ .arg(o10).arg(o11);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8, const T9 &o9,
+ const T10 &o10, const T11 &o11, const T12 &o12)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+ .arg(o10).arg(o11).arg(o12);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8, const T9 &o9,
+ const T10 &o10, const T11 &o11, const T12 &o12,
+ const T13 &o13)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+ .arg(o10).arg(o11).arg(o12).arg(o13);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8, const T9 &o9,
+ const T10 &o10, const T11 &o11, const T12 &o12,
+ const T13 &o13, const T14 &o14)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+ .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
+ return c.str();
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14,
+ typename T15>
+ inline std::string compose(const std::string &fmt,
+ const T1 &o1, const T2 &o2, const T3 &o3,
+ const T4 &o4, const T5 &o5, const T6 &o6,
+ const T7 &o7, const T8 &o8, const T9 &o9,
+ const T10 &o10, const T11 &o11, const T12 &o12,
+ const T13 &o13, const T14 &o14, const T15 &o15)
+ {
+ StringPrivate::Composition c(fmt);
+ c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+ .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
+ return c.str();
+ }
+//}
+
+
+#endif // STRING_COMPOSE_H
diff --git a/libs/pbd3/pbd/datum.h b/libs/pbd3/pbd/datum.h
new file mode 100644
index 0000000000..1f2704b429
--- /dev/null
+++ b/libs/pbd3/pbd/datum.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qm_datum_h__
+#define __qm_datum_h__
+
+/* A basic data type used whenever we want to represent
+ something that might be a string or a number.
+*/
+
+struct Datum {
+ enum Type {
+ String,
+ Numeric,
+ };
+ Type type;
+ union {
+ const char *str;
+ float n;
+ };
+
+ Datum &operator=(float val) {
+ type = Numeric;
+ n = val;
+ return *this;
+ }
+
+ Datum &operator=(int val) {
+ type = Numeric;
+ n=(float) val;
+ return *this;
+ }
+
+ Datum &operator=(const char *val) {
+ type = String;
+ str = val;
+ return *this;
+ }
+};
+
+#endif // __qm_datum_h__
diff --git a/libs/pbd3/pbd/dirname.h b/libs/pbd3/pbd/dirname.h
new file mode 100644
index 0000000000..5e63ddb55d
--- /dev/null
+++ b/libs/pbd3/pbd/dirname.h
@@ -0,0 +1,11 @@
+#ifndef __stupid_dirname_h__
+#define __stupid_dirname_h__
+
+
+#include <string>
+
+namespace PBD {
+ extern char *dirname (const char *);
+ extern std::string dirname (const std::string);
+}
+#endif // __stupid_dirname_h__
diff --git a/libs/pbd3/pbd/ellipsoid.h b/libs/pbd3/pbd/ellipsoid.h
new file mode 100644
index 0000000000..3758e415c2
--- /dev/null
+++ b/libs/pbd3/pbd/ellipsoid.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qm_ellipsoid_h__
+#define __qm_ellipsoid_h__
+
+struct Arc
+{
+ int rect_x;
+ int rect_y;
+ int rect_h;
+ int rect_w;
+ int start_angle;
+ int arc_angle;
+ bool counter_clockwise;
+};
+
+class Ellipsoid
+{
+ int start_x;
+ int end_x;
+ int start_y;
+ int end_y;
+ static const unsigned int narcs;
+
+ public:
+ Arc arc[2];
+
+ Ellipsoid () {
+ start_x = -1;
+ end_x = -1;
+ }
+
+ bool ready() { return start_x != -1 && end_x != -1; }
+ void set_start (int x, int y);
+ void set_end (int x, int y);
+ void compute ();
+
+ void set_start_angle (int n, int which_arc = -1) {
+ if (which_arc < 0) {
+ arc[0].start_angle = n * 64;
+ arc[1].start_angle = n * 64;
+ } else if (which_arc < (int) narcs) {
+ arc[which_arc].start_angle = n * 64;
+ }
+ }
+ void set_arc_angle (int n, int which_arc = -1) {
+ if (which_arc < 0) {
+ arc[0].arc_angle = n * 64;
+ arc[1].arc_angle = n * 64;
+ } else if (which_arc < (int) narcs) {
+ arc[which_arc].arc_angle = n * 64;
+ }
+ }
+};
+
+#endif // __qm_ellipsoid_h__
diff --git a/libs/pbd3/pbd/error.h b/libs/pbd3/pbd/error.h
new file mode 100644
index 0000000000..cb822e6210
--- /dev/null
+++ b/libs/pbd3/pbd/error.h
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+#ifndef __libmisc_error_h__
+#define __libmisc_error_h__
+
+#include "transmitter.h"
+
+extern Transmitter error;
+extern Transmitter info;
+extern Transmitter warning;
+extern Transmitter fatal;
+
+#endif // __libmisc_error_h__
diff --git a/libs/pbd3/pbd/failed_constructor.h b/libs/pbd3/pbd/failed_constructor.h
new file mode 100644
index 0000000000..62eb6c0d71
--- /dev/null
+++ b/libs/pbd3/pbd/failed_constructor.h
@@ -0,0 +1,11 @@
+#ifndef __pbd_failed_constructor_h__
+#define __pbd_failed_constructor_h__
+
+#include <exception>
+
+class failed_constructor : public std::exception {
+ public:
+ virtual const char *what() const throw() { return "failed constructor"; }
+};
+
+#endif /* __pbd_failed_constructor_h__ */
diff --git a/libs/pbd3/pbd/fastlog.h b/libs/pbd3/pbd/fastlog.h
new file mode 100644
index 0000000000..4e9050cb8b
--- /dev/null
+++ b/libs/pbd3/pbd/fastlog.h
@@ -0,0 +1,38 @@
+/* Copyright unknown. Code by Laurent de Soras <laurent@ohmforce.com>.
+ */
+
+#ifndef __pbd_fastlog_h__
+#define __pbd_fastlog_h__
+
+#include <math.h> /* for HUGE_VAL */
+
+static inline float fast_log2 (float val)
+{
+ /* don't use reinterpret_cast<> because that prevents this
+ from being used by pure C code (for example, GnomeCanvasItems)
+ */
+ int * const exp_ptr = (int *)(&val);
+ int x = *exp_ptr;
+ const int log_2 = ((x >> 23) & 255) - 128;
+ x &= ~(255 << 23);
+ x += 127 << 23;
+ *exp_ptr = x;
+
+ val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1)
+
+ return (val + log_2);
+}
+
+static inline float fast_log (const float val)
+{
+ return (fast_log2 (val) * 0.69314718f);
+}
+
+static inline float fast_log10 (const float val)
+{
+ return fast_log2(val) / 3.312500f;
+}
+
+static inline float minus_infinity() { return -HUGE_VAL; }
+
+#endif /* __pbd_fastlog_h__ */
diff --git a/libs/pbd3/pbd/foreach.h b/libs/pbd3/pbd/foreach.h
new file mode 100644
index 0000000000..5102d81bb0
--- /dev/null
+++ b/libs/pbd3/pbd/foreach.h
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2002 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __lib_pbd_foreach_h__
+#define __lib_pbd_foreach_h__
+
+template<class Iter, class T> void foreach (Iter first, Iter last, void (T::*method)()) {
+ for (; first != last; ++first) {
+ ((*first).*method)();
+ }
+}
+
+template<class Iter, class T, class A> void foreach (Iter first, Iter last, void (T::*method)(A a), A arg) {
+ for (; first != last; ++first) {
+ ((*first).*method)(arg);
+ }
+}
+
+template<class Iter, class T, class A1, class A2> void foreach (Iter first, Iter last, void (T::*method)(A1, A2), A1 arg1, A2 arg2) {
+ for (; first != last; ++first) {
+ ((*first).*method)(arg1, arg2);
+ }
+}
+
+#endif /* __lib_pbd_foreach_h__ */
diff --git a/libs/pbd3/pbd/forkexec.h b/libs/pbd3/pbd/forkexec.h
new file mode 100644
index 0000000000..2af3711390
--- /dev/null
+++ b/libs/pbd3/pbd/forkexec.h
@@ -0,0 +1,9 @@
+#ifndef __forkexec_h__
+#define __forkexec_h__
+
+#include <unistd.h>
+
+pid_t forkexec(char **argv, char **envp, int outpipe[2], int inpipe[2]);
+pid_t forkexec_cmd(char *cmd, char **envp, int outpipe[2], int inpipe[2]);
+
+#endif // __forkexec_h__
diff --git a/libs/pbd3/pbd/ftw.h b/libs/pbd3/pbd/ftw.h
new file mode 100644
index 0000000000..9acf8a6967
--- /dev/null
+++ b/libs/pbd3/pbd/ftw.h
@@ -0,0 +1,106 @@
+/*
+ Copyright (c) 2003 by Joel Baker.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the Author nor the names of any contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+#ifndef _FTW_H
+#define _FTW_H
+
+#include <sys/stat.h>
+
+/* Enumerated values for 'flag' when calling [n]ftw */
+
+enum {
+ FTW_D, /* Directories */
+ FTW_DNR, /* Unreadable directory */
+ FTW_F, /* Regular files */
+ FTW_SL, /* Symbolic link */
+ FTW_NS, /* stat(2) failed */
+
+#ifdef __USE_XOPEN_EXTENDED /* X/Open */
+
+/* Flags for nftw only */
+
+ FTW_DP, /* Directory, subdirs visited */
+ FTW_SLN, /* Dangling symlink */
+
+#endif /* __USE_XOPEN_EXTENDED */
+};
+
+#ifdef __USE_XOPEN_EXTENDED /* X/Open */
+
+/* Enumerated values for 'flags' when calling nftw */
+
+enum {
+ FTW_CHDIR = 1, /* Do a chdir(2) when entering a directory */
+ FTW_DEPTH = 2, /* Report files first (before directory) */
+ FTW_MOUNT = 4, /* Single filesystem */
+ FTW_PHYS = 8 /* Physical walk; ignore symlinks */
+};
+
+#define FTW_PHYS FTW_PHYS
+#define FTW_MOUNT FTW_MOUNT
+#define FTW_CHDIR FTW_CHDIR
+#define FTW_DEPTH FTW_DEPTH
+
+/* FTW struct for callbacks from nftw */
+
+struct FTW {
+ int base;
+ int level;
+};
+
+#endif /* __USE_XOPEN_EXTENDED */
+
+/* Typecasts for callback functions */
+
+typedef int (*__ftw_func_t) \
+ (const char *file, const struct stat *status, int flag);
+
+#ifdef __USE_XOPEN_EXTENDED /* X/Open */
+
+typedef int (*__nftw_func_t) \
+ (const char *file, const struct stat *status, int flag, struct FTW *detail);
+
+#endif /* __USE_XOPEN_EXTENDED */
+
+/* ftw: walk a directory tree, calling a function for each element */
+
+extern int ftw (const char *dir, __ftw_func_t func, int descr);
+
+#ifdef __USE_XOPEN_EXTENDED /* X/Open */
+
+/* nftw: walk a directory tree, calling a function for each element; much
+ * like ftw, but with behavior flags and minty freshness.
+ */
+
+extern int nftw (const char *dir, __nftw_func_t func, int descr, int flags);
+
+#endif /* __USE_XOPEN_EXTENDED */
+
+#endif /* _FTW_H */
diff --git a/libs/pbd3/pbd/irix_platform.h b/libs/pbd3/pbd/irix_platform.h
new file mode 100644
index 0000000000..f948554f26
--- /dev/null
+++ b/libs/pbd3/pbd/irix_platform.h
@@ -0,0 +1,20 @@
+#ifndef __irix_platform__
+#define __irix_platform__
+
+#include <pbd/platform.h>
+
+class IrixPlatform : public Platform {
+ public:
+ IrixPlatform () : Platform () {};
+ virtual ~IrixPlatform ();
+
+ virtual int pre_config ();
+ virtual int post_config ();
+ virtual int pre_ui ();
+ virtual int post_ui ();
+
+ virtual int dsp_startup();
+};
+
+
+#endif // __irix_platform__
diff --git a/libs/pbd3/pbd/linux_platform.h b/libs/pbd3/pbd/linux_platform.h
new file mode 100644
index 0000000000..74822a9d89
--- /dev/null
+++ b/libs/pbd3/pbd/linux_platform.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __linux_platform_h__
+#define __linux_platform_h__
+
+#include <pbd/platform.h>
+
+class LinuxPlatform : public Platform
+
+{
+ public:
+ LinuxPlatform ();
+ ~LinuxPlatform () {};
+
+ int pre_config ();
+ int post_config ();
+ int pre_ui ();
+ int post_ui ();
+
+ int dsp_startup() { return 0; }
+};
+
+#endif // __linux_platform_h__
diff --git a/libs/pbd3/pbd/lock_free_fifo.h b/libs/pbd3/pbd/lock_free_fifo.h
new file mode 100644
index 0000000000..cbe653fcb5
--- /dev/null
+++ b/libs/pbd3/pbd/lock_free_fifo.h
@@ -0,0 +1,86 @@
+/*
+ Copyright (C) 2000 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_lockfree_fifo_h__
+#define __pbd_lockfree_fifo_h__
+
+#include <sys/types.h>
+#include <cstdlib>
+
+template<class T>
+class LockFreeFIFO
+{
+public:
+ LockFreeFIFO (int sz) {
+ size = sz;
+ push_ptr = 0;
+ pop_ptr = 0;
+ buf = new T[size];
+ };
+
+ virtual ~LockFreeFIFO() {
+ delete [] buf;
+ }
+
+
+ int pop (T& r) {
+ if (pop_ptr == push_ptr) {
+ return -1;
+ } else {
+ r = buf[pop_ptr];
+ pop_ptr++;
+ if (pop_ptr >= size) {
+ pop_ptr = 0;
+ }
+ return 0;
+ }
+ }
+
+ int top (T& r) {
+ if (pop_ptr == push_ptr) {
+ return -1;
+ } else {
+ r = buf[pop_ptr];
+ return 0;
+ }
+ }
+
+ int push (T& t) {
+ if ((size_t) abs (static_cast<int>(push_ptr - pop_ptr)) < size) {
+ buf[push_ptr] = t;
+ push_ptr++;
+ if (push_ptr >= size) {
+ push_ptr = 0;
+ }
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ protected:
+ T *buf;
+ volatile size_t push_ptr;
+ volatile size_t pop_ptr;
+ size_t size;
+};
+
+
+#endif /* __pbd_lockfree_fifo_h__ */
diff --git a/libs/pbd3/pbd/lockmonitor.h b/libs/pbd3/pbd/lockmonitor.h
new file mode 100644
index 0000000000..8fad66f83e
--- /dev/null
+++ b/libs/pbd3/pbd/lockmonitor.h
@@ -0,0 +1,194 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_lockmonitor_h__
+#define __pbd_lockmonitor_h__
+
+#include <pthread.h>
+#include <pbd/pthread_spinlock.h>
+
+#undef DEBUG_LOCK_MONITOR
+
+#ifdef DEBUG_LOCK_MONITOR
+#include <iostream>
+#include <ardour/cycles.h>
+#endif
+
+namespace PBD
+{
+class Lock {
+ public:
+ Lock() { pthread_mutex_init (&_mutex, 0); }
+ virtual ~Lock() {}
+
+ virtual int lock () { return pthread_mutex_lock (&_mutex); }
+ virtual int unlock() { return pthread_mutex_unlock (&_mutex); }
+
+ pthread_mutex_t *mutex() { return &_mutex; }
+
+ protected:
+ pthread_mutex_t _mutex;
+};
+
+class NonBlockingLock : public Lock {
+ public:
+ NonBlockingLock() {}
+ ~NonBlockingLock(){}
+
+ int lock () { return pthread_mutex_lock (&_mutex); }
+ int trylock () { return pthread_mutex_trylock (&_mutex); }
+ int unlock() { return pthread_mutex_unlock (&_mutex); }
+};
+
+class LockMonitor
+{
+ public:
+ LockMonitor (Lock& lck, unsigned long l, const char *f)
+ : lock (lck)
+#ifdef DEBUG_LOCK_MONITOR
+ , line (l), file (f)
+#endif
+ {
+
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long long when;
+ when = get_cycles();
+ cerr << when << " lock " << &lock << " at " << line << " in " << file << endl;
+#endif
+ lock.lock ();
+#ifdef DEBUG_LOCK_MONITOR
+ when = get_cycles();
+ cerr << '\t' << when
+ << " locked: "
+ << &lock << " at "
+ << line << " in " << file << endl;
+#endif
+ }
+
+ ~LockMonitor () {
+ lock.unlock ();
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long long when;
+ when = get_cycles();
+ cerr << '\t' << when << ' '
+ << " UNLOCKED "
+ << &lock << " at "
+ << line << " in " << file << endl;
+#endif
+ }
+ private:
+ Lock& lock;
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long line;
+ const char * file;
+#endif
+};
+
+class TentativeLockMonitor
+{
+ public:
+ TentativeLockMonitor (NonBlockingLock& lck, unsigned long l, const char *f)
+ : lock (lck)
+#ifdef DEBUG_LOCK_MONITOR
+ , line (l), file (f)
+#endif
+ {
+
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long long when;
+ when = get_cycles();
+ cerr << when << " tentative lock " << &lock << " at " << line << " in " << file << endl;
+#endif
+ _locked = (lock.trylock() == 0);
+
+#ifdef DEBUG_LOCK_MONITOR
+ when = get_cycles();
+ cerr << '\t' << when << ' '
+ << _locked
+ << " lock: "
+ << &lock << " at "
+ << line << " in " << file << endl;
+#endif
+ }
+
+ ~TentativeLockMonitor () {
+ if (_locked) {
+ lock.unlock ();
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long long when;
+ when = get_cycles();
+ cerr << '\t' << when << ' '
+ << " UNLOCKED "
+ << &lock << " at "
+ << line << " in " << file << endl;
+#endif
+ }
+ }
+
+ bool locked() { return _locked; }
+
+ private:
+ NonBlockingLock& lock;
+ bool _locked;
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long line;
+ const char * file;
+#endif
+};
+
+class SpinLockMonitor
+{
+ public:
+ SpinLockMonitor (pthread_mutex_t *lck, unsigned long l, const char *f)
+ : lock (lck)
+#ifdef DEBUG_LOCK_MONITOR
+ , line (l), file (f)
+#endif
+ {
+
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long long when;
+ when = get_cycles();
+ cerr << when << " spinlock " << lck << " at " << line << " in " << file << endl;
+#endif
+ pthread_mutex_spinlock (lck);
+#ifdef DEBUG_LOCK_MONITOR
+ when = get_cycles();
+ cerr << '\t' << when
+ << " locked at "
+ << &lock << " at "
+ << line << " in " << file << endl;
+#endif
+ }
+
+ ~SpinLockMonitor () {
+ pthread_mutex_unlock (lock);
+ }
+ private:
+ pthread_mutex_t *lock;
+#ifdef DEBUG_LOCK_MONITOR
+ unsigned long line;
+ const char * file;
+#endif
+};
+
+} /* namespace */
+
+#endif /* __pbd_lockmonitor_h__*/
diff --git a/libs/pbd3/pbd/mountpoint.h b/libs/pbd3/pbd/mountpoint.h
new file mode 100644
index 0000000000..86ccc58190
--- /dev/null
+++ b/libs/pbd3/pbd/mountpoint.h
@@ -0,0 +1,28 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_mountpoint_h__
+#define __pbd_mountpoint_h__
+
+#include <string>
+
+std::string mountpoint (std::string path);
+
+#endif // __pbd_mountpoint_h__
diff --git a/libs/pbd3/pbd/pathscanner.h b/libs/pbd3/pbd/pathscanner.h
new file mode 100644
index 0000000000..346e7858c4
--- /dev/null
+++ b/libs/pbd3/pbd/pathscanner.h
@@ -0,0 +1,66 @@
+#ifndef __libmisc_pathscanner_h__
+#define __libmisc_pathscanner_h__
+
+#include <vector>
+#include <string>
+#include <regex.h>
+
+using std::string;
+using std::vector;
+
+class PathScanner
+
+{
+ public:
+ vector<string *> *operator() (const string &dirpath,
+ bool (*filter)(const string &, void *arg),
+ void *arg,
+ bool match_fullpath = true,
+ bool return_fullpath = true,
+ long limit = -1) {
+ return run_scan (dirpath,
+ (bool (PathScanner::*)(const string &)) 0,
+ filter,
+ arg,
+ match_fullpath,
+ return_fullpath,
+ limit);
+ }
+
+ vector<string *> *operator() (const string &dirpath,
+ const string &regexp,
+ bool match_fullpath = true,
+ bool return_fullpath = true,
+ long limit = -1);
+
+
+ string *find_first (const string &dirpath,
+ const string &regexp,
+ bool match_fullpath = true,
+ bool return_fullpath = true);
+
+ string *find_first (const string &dirpath,
+ bool (*filter)(const string &, void *),
+ void *arg,
+ bool match_fullpath = true,
+ bool return_fullpath = true);
+
+ private:
+ regex_t compiled_pattern;
+
+ bool regexp_filter (const string &str) {
+ return regexec (&compiled_pattern, str.c_str(), 0, 0, 0) == 0;
+ }
+
+ vector<string *> *run_scan (const string &dirpath,
+ bool (PathScanner::*mfilter) (const string &),
+ bool (*filter)(const string &, void *),
+ void *arg,
+ bool match_fullpath,
+ bool return_fullpath,
+ long limit);
+
+
+};
+
+#endif // __libmisc_pathscanner_h__
diff --git a/libs/pbd3/pbd/platform.h b/libs/pbd3/pbd/platform.h
new file mode 100644
index 0000000000..761195a31b
--- /dev/null
+++ b/libs/pbd3/pbd/platform.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qm_platform_h__
+#define __qm_platform_h__
+
+class Platform
+
+{
+ public:
+ Platform () {
+ thePlatform = this;
+ }
+ virtual ~Platform () {}
+
+ virtual int pre_config () { return 0;}
+ virtual int post_config () { return 0;}
+ virtual int pre_ui () { return 0; }
+ virtual int post_ui () { return 0; }
+ virtual int dsp_startup() { return 0; }
+
+ static Platform *instance() { return thePlatform; }
+
+ private:
+ static Platform *thePlatform;
+};
+
+#endif // __qm_platform_h__
diff --git a/libs/pbd3/pbd/platform_factory.h b/libs/pbd3/pbd/platform_factory.h
new file mode 100644
index 0000000000..d5255ea212
--- /dev/null
+++ b/libs/pbd3/pbd/platform_factory.h
@@ -0,0 +1,12 @@
+#ifndef __platform_factory__
+#define __platform_factory__
+
+#include <pbd/platform.h>
+
+class PlatformFactory {
+public:
+ static Platform* create_platform ();
+};
+
+
+#endif // __platform_factory__
diff --git a/libs/pbd3/pbd/pool.h b/libs/pbd3/pbd/pool.h
new file mode 100644
index 0000000000..c8e9740acd
--- /dev/null
+++ b/libs/pbd3/pbd/pool.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qm_pool_h__
+#define __qm_pool_h__
+
+#include <vector>
+#include <string>
+#include <pthread.h>
+#include <pbd/ringbuffer.h>
+
+class Pool
+{
+ public:
+ Pool (std::string name, unsigned long item_size, unsigned long nitems);
+ virtual ~Pool ();
+
+ virtual void *alloc ();
+ virtual void release (void *);
+
+ std::string name() const { return _name; }
+
+ private:
+ RingBuffer<void*>* free_list;
+ std::string _name;
+ void *block;
+};
+
+class SingleAllocMultiReleasePool : public Pool
+{
+ public:
+ SingleAllocMultiReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
+ ~SingleAllocMultiReleasePool ();
+
+ virtual void *alloc ();
+ virtual void release (void *);
+
+ private:
+ pthread_mutex_t lock;
+};
+
+
+class MultiAllocSingleReleasePool : public Pool
+{
+ public:
+ MultiAllocSingleReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
+ ~MultiAllocSingleReleasePool ();
+
+ virtual void *alloc ();
+ virtual void release (void *);
+
+ private:
+ pthread_mutex_t lock;
+};
+
+
+#endif // __qm_pool_h__
diff --git a/libs/pbd3/pbd/position.h b/libs/pbd3/pbd/position.h
new file mode 100644
index 0000000000..c8241af085
--- /dev/null
+++ b/libs/pbd3/pbd/position.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qui_position_h__
+#define __qui_position_h__
+
+enum Position {
+ Top,
+ Left,
+ Right,
+ Bottom,
+ UpperLeft,
+ LowerLeft,
+ UpperRight,
+ LowerRight,
+ Center,
+ Nowhere,
+};
+
+
+#endif // __qui_position_h__
diff --git a/libs/pbd3/pbd/precision_timer.h b/libs/pbd3/pbd/precision_timer.h
new file mode 100644
index 0000000000..a103b4800d
--- /dev/null
+++ b/libs/pbd3/pbd/precision_timer.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __precision_timer_h__
+#define __precision_timer_h__
+
+#include <pbd/cycles.h>
+
+typedef cycles_t precision_time_t;
+
+class PrecisionTimer {
+ public:
+ PrecisionTimer ();
+
+ /* returns current time in microseconds since
+ the time base was created (which may be
+ the same as when the PrecisionTimer was
+ created or it may not).
+ */
+
+#ifdef PBD_HAVE_CYCLE_COUNTER
+
+ precision_time_t current () {
+ return get_cycles() / cycles_per_usec;
+ }
+
+#else /* !HAVE_CYCLE_COUNTER */
+
+ precision_time_t current () {
+ struct timeval now;
+ gettimeofday (&now, 0);
+ return (precision_time_t) ((now.tv_sec * 1000000) + now.tv_usec);
+ }
+
+#endif /* HAVE_CYCLE_COUNTER */
+
+ private:
+ int get_mhz();
+ static precision_time_t cycles_per_usec;
+};
+
+#endif // __precision_timer.h
+
+
diff --git a/libs/pbd3/pbd/pthread_spinlock.h b/libs/pbd3/pbd/pthread_spinlock.h
new file mode 100644
index 0000000000..71835221fa
--- /dev/null
+++ b/libs/pbd3/pbd/pthread_spinlock.h
@@ -0,0 +1,29 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+#ifndef __pthread_mutex_spinlock_h__
+#define __pthread_mutex_spinlock_h__
+
+#include <pthread.h>
+
+extern unsigned int pthread_calibrate_spinlimit ();
+extern void pthread_set_spinlimit (unsigned int spins);
+extern int pthread_mutex_spinlock (pthread_mutex_t *mp);
+
+#endif // __pthread_mutex_spinlock_h__
diff --git a/libs/pbd3/pbd/pthread_utils.h b/libs/pbd3/pbd/pthread_utils.h
new file mode 100644
index 0000000000..9c7cefd3e4
--- /dev/null
+++ b/libs/pbd3/pbd/pthread_utils.h
@@ -0,0 +1,21 @@
+#ifndef __pbd_pthread_utils__
+#define __pbd_pthread_utils__
+
+#include <pthread.h>
+#include <signal.h>
+#include <string>
+
+#include <sigc++/sigc++.h>
+
+int pthread_create_and_store (std::string name, pthread_t *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg);
+void pthread_cancel_one (pthread_t thread);
+void pthread_kill_all (int signum);
+void pthread_cancel_all ();
+void pthread_exit_pbd (void* status);
+std::string pthread_name ();
+
+namespace PBD {
+ extern sigc::signal<void,pthread_t,std::string> ThreadCreated;
+}
+
+#endif /* __pbd_pthread_utils__ */
diff --git a/libs/pbd3/pbd/rcpointer.h b/libs/pbd3/pbd/rcpointer.h
new file mode 100644
index 0000000000..c634208437
--- /dev/null
+++ b/libs/pbd3/pbd/rcpointer.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qm_rcpointer_h__
+#define __qm_rcpointer_h__
+
+template<class T> class RCPointer {
+ public:
+ T *operator->() { return _ptr; }
+ bool operator==(T *p) { return _ptr == p; }
+ bool operator!=(T *p) { return _ptr != p; }
+
+ int refcount() { return _ptr->count; }
+
+ RCPointer () { _ptr = 0; }
+
+ RCPointer (T *p) : _ptr (p) {
+ if (_ptr) _ptr->count++;
+ }
+
+ RCPointer (const RCPointer& r) : _ptr (r._ptr) {
+ if (_ptr) _ptr->count++;
+ }
+
+ RCPointer &operator= (const RCPointer &r) {
+ if (_ptr == r._ptr) return *this;
+ if (_ptr && --_ptr->count == 0) {
+ delete _ptr;
+ }
+ _ptr = r._ptr;
+ if (_ptr) _ptr->count++;
+ return *this;
+ }
+ ~RCPointer () {
+ if (_ptr && --_ptr->count == 0) {
+ delete _ptr;
+ }
+ }
+
+ private:
+ T *_ptr;
+};
+
+#endif // __qm_rcpointer_h__
diff --git a/libs/pbd3/pbd/receiver.h b/libs/pbd3/pbd/receiver.h
new file mode 100644
index 0000000000..b55e28f5ee
--- /dev/null
+++ b/libs/pbd3/pbd/receiver.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __libmisc_receiver_h__
+#define __libmisc_receiver_h__
+
+#include <vector>
+
+#include <sigc++/sigc++.h>
+
+#include "transmitter.h"
+
+using std::vector;
+
+class strstream;
+
+class Receiver : public sigc::trackable
+{
+ public:
+ Receiver ();
+ virtual ~Receiver ();
+
+ void listen_to (Transmitter &);
+ void hangup ();
+
+ protected:
+ virtual void receive (Transmitter::Channel, const char *) = 0;
+
+ private:
+ vector<sigc::connection *> connections;
+};
+
+#endif // __libmisc_receiver_h__
diff --git a/libs/pbd3/pbd/relation.h b/libs/pbd3/pbd/relation.h
new file mode 100644
index 0000000000..f28aaecfa1
--- /dev/null
+++ b/libs/pbd3/pbd/relation.h
@@ -0,0 +1,35 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_relation_h__
+#define __pbd_relation_h__
+
+enum RelationalCondition {
+ Equal = 0,
+ NotEqual,
+ LessThan,
+ LessThanOrEqual,
+ GreaterThan,
+ GreaterThanOrEqual,
+ Changed,
+
+ NumConditions
+};
+
+#endif // __pbd_relation_h__
diff --git a/libs/pbd3/pbd/restartable_rw.h b/libs/pbd3/pbd/restartable_rw.h
new file mode 100644
index 0000000000..ee84e4e295
--- /dev/null
+++ b/libs/pbd3/pbd/restartable_rw.h
@@ -0,0 +1,7 @@
+#ifndef __libmisc_restartable_rw__h__
+#define __libmisc_restartable_rw__h__
+
+extern int restartable_write (int fd, unsigned char *buf, size_t cnt);
+extern int restartable_read (int fd, unsigned char *buf, size_t cnt);
+
+#endif // __libmisc_restartable_rw__h__
diff --git a/libs/pbd3/pbd/ringbuffer.h b/libs/pbd3/pbd/ringbuffer.h
new file mode 100644
index 0000000000..cca9cbfc01
--- /dev/null
+++ b/libs/pbd3/pbd/ringbuffer.h
@@ -0,0 +1,283 @@
+/*
+ Copyright (C) 2000 Paul Davis & Benno Senoner
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef ringbuffer_h
+#define ringbuffer_h
+
+#include <sys/mman.h>
+#include <pbd/atomic.h>
+
+template<class T>
+class RingBuffer
+{
+ public:
+ RingBuffer (size_t sz) {
+ size_t power_of_two;
+
+ for (power_of_two = 1; 1U<<power_of_two < sz; power_of_two++);
+
+ size = 1<<power_of_two;
+ size_mask = size;
+ size_mask -= 1;
+ buf = new T[size];
+ reset ();
+
+ };
+
+ virtual ~RingBuffer() {
+ delete [] buf;
+ }
+
+ void reset () {
+ /* !!! NOT THREAD SAFE !!! */
+ atomic_set (&write_ptr, 0);
+ atomic_set (&read_ptr, 0);
+ }
+
+ void set (size_t r, size_t w) {
+ /* !!! NOT THREAD SAFE !!! */
+ atomic_set (&write_ptr, w);
+ atomic_set (&read_ptr, r);
+ }
+
+ size_t read (T *dest, size_t cnt);
+ size_t write (T *src, size_t cnt);
+
+ struct rw_vector {
+ T *buf[2];
+ size_t len[2];
+ };
+
+ void get_read_vector (rw_vector *);
+ void get_write_vector (rw_vector *);
+
+ void decrement_read_ptr (size_t cnt) {
+ atomic_set (&read_ptr, (atomic_read(&read_ptr) - cnt) & size_mask);
+ }
+
+ void increment_read_ptr (size_t cnt) {
+ atomic_set (&read_ptr, (atomic_read(&read_ptr) + cnt) & size_mask);
+ }
+
+ void increment_write_ptr (size_t cnt) {
+ atomic_set (&write_ptr, (atomic_read(&write_ptr) + cnt) & size_mask);
+ }
+
+ size_t write_space () {
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ return ((r - w + size) & size_mask) - 1;
+ } else if (w < r) {
+ return (r - w) - 1;
+ } else {
+ return size - 1;
+ }
+ }
+
+ size_t read_space () {
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ return w - r;
+ } else {
+ return (w - r + size) & size_mask;
+ }
+ }
+
+ T *buffer () { return buf; }
+ size_t get_write_ptr () const { return atomic_read (&write_ptr); }
+ size_t get_read_ptr () const { return atomic_read (&read_ptr); }
+ size_t bufsize () const { return size; }
+
+ protected:
+ T *buf;
+ size_t size;
+ atomic_t write_ptr;
+ atomic_t read_ptr;
+ size_t size_mask;
+};
+
+template<class T> size_t
+RingBuffer<T>::read (T *dest, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_read;
+ size_t n1, n2;
+ size_t priv_read_ptr;
+
+ priv_read_ptr=atomic_read(&read_ptr);
+
+ if ((free_cnt = read_space ()) == 0) {
+ return 0;
+ }
+
+ to_read = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = priv_read_ptr + to_read;
+
+ if (cnt2 > size) {
+ n1 = size - priv_read_ptr;
+ n2 = cnt2 & size_mask;
+ } else {
+ n1 = to_read;
+ n2 = 0;
+ }
+
+ memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
+ priv_read_ptr = (priv_read_ptr + n1) & size_mask;
+
+ if (n2) {
+ memcpy (dest+n1, buf, n2 * sizeof (T));
+ priv_read_ptr = n2;
+ }
+
+ atomic_set(&read_ptr, priv_read_ptr);
+ return to_read;
+}
+
+template<class T> size_t
+RingBuffer<T>::write (T *src, size_t cnt)
+
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_write;
+ size_t n1, n2;
+ size_t priv_write_ptr;
+
+ priv_write_ptr=atomic_read(&write_ptr);
+
+ if ((free_cnt = write_space ()) == 0) {
+ return 0;
+ }
+
+ to_write = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = priv_write_ptr + to_write;
+
+ if (cnt2 > size) {
+ n1 = size - priv_write_ptr;
+ n2 = cnt2 & size_mask;
+ } else {
+ n1 = to_write;
+ n2 = 0;
+ }
+
+ memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
+ priv_write_ptr = (priv_write_ptr + n1) & size_mask;
+
+ if (n2) {
+ memcpy (buf, src+n1, n2 * sizeof (T));
+ priv_write_ptr = n2;
+ }
+
+ atomic_set(&write_ptr, priv_write_ptr);
+ return to_write;
+}
+
+template<class T> void
+RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec)
+
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ free_cnt = w - r;
+ } else {
+ free_cnt = (w - r + size) & size_mask;
+ }
+
+ cnt2 = r + free_cnt;
+
+ if (cnt2 > size) {
+ /* Two part vector: the rest of the buffer after the
+ current write ptr, plus some from the start of
+ the buffer.
+ */
+
+ vec->buf[0] = &buf[r];
+ vec->len[0] = size - r;
+ vec->buf[1] = buf;
+ vec->len[1] = cnt2 & size_mask;
+
+ } else {
+
+ /* Single part vector: just the rest of the buffer */
+
+ vec->buf[0] = &buf[r];
+ vec->len[0] = free_cnt;
+ vec->len[1] = 0;
+ }
+}
+
+template<class T> void
+RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec)
+
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ free_cnt = ((r - w + size) & size_mask) - 1;
+ } else if (w < r) {
+ free_cnt = (r - w) - 1;
+ } else {
+ free_cnt = size - 1;
+ }
+
+ cnt2 = w + free_cnt;
+
+ if (cnt2 > size) {
+
+ /* Two part vector: the rest of the buffer after the
+ current write ptr, plus some from the start of
+ the buffer.
+ */
+
+ vec->buf[0] = &buf[w];
+ vec->len[0] = size - w;
+ vec->buf[1] = buf;
+ vec->len[1] = cnt2 & size_mask;
+ } else {
+ vec->buf[0] = &buf[w];
+ vec->len[0] = free_cnt;
+ vec->len[1] = 0;
+ }
+}
+
+
+#endif /* __ringbuffer_h__ */
diff --git a/libs/pbd3/pbd/ringbufferNPT.h b/libs/pbd3/pbd/ringbufferNPT.h
new file mode 100644
index 0000000000..d0562ec76b
--- /dev/null
+++ b/libs/pbd3/pbd/ringbufferNPT.h
@@ -0,0 +1,272 @@
+/*
+ Copyright (C) 2000 Paul Davis & Benno Senoner
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef ringbuffer_npt_h
+#define ringbuffer_npt_h
+
+#include <sys/mman.h>
+#include <pbd/atomic.h>
+
+template<class T>
+class RingBufferNPT
+{
+ public:
+ RingBufferNPT (size_t sz) {
+ size = sz;
+ buf = new T[size];
+ reset ();
+
+ };
+
+ virtual ~RingBufferNPT() {
+ delete [] buf;
+ }
+
+ void reset () {
+ /* !!! NOT THREAD SAFE !!! */
+ atomic_set (&write_ptr, 0);
+ atomic_set (&read_ptr, 0);
+ }
+
+ void set (size_t r, size_t w) {
+ /* !!! NOT THREAD SAFE !!! */
+ atomic_set (&write_ptr, w);
+ atomic_set (&read_ptr, r);
+ }
+
+ size_t read (T *dest, size_t cnt);
+ size_t write (T *src, size_t cnt);
+
+ struct rw_vector {
+ T *buf[2];
+ size_t len[2];
+ };
+
+ void get_read_vector (rw_vector *);
+ void get_write_vector (rw_vector *);
+
+ void decrement_read_ptr (size_t cnt) {
+ atomic_set (&read_ptr, (atomic_read(&read_ptr) - cnt) % size);
+ }
+
+ void increment_read_ptr (size_t cnt) {
+ atomic_set (&read_ptr, (atomic_read(&read_ptr) + cnt) % size);
+ }
+
+ void increment_write_ptr (size_t cnt) {
+ atomic_set (&write_ptr, (atomic_read(&write_ptr) + cnt) % size);
+ }
+
+ size_t write_space () {
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ return ((r - w + size) % size) - 1;
+ } else if (w < r) {
+ return (r - w) - 1;
+ } else {
+ return size - 1;
+ }
+ }
+
+ size_t read_space () {
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ return w - r;
+ } else {
+ return (w - r + size) % size;
+ }
+ }
+
+ T *buffer () { return buf; }
+ size_t get_write_ptr () const { return atomic_read (&write_ptr); }
+ size_t get_read_ptr () const { return atomic_read (&read_ptr); }
+ size_t bufsize () const { return size; }
+
+ protected:
+ T *buf;
+ size_t size;
+ atomic_t write_ptr;
+ atomic_t read_ptr;
+};
+
+template<class T> size_t
+RingBufferNPT<T>::read (T *dest, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_read;
+ size_t n1, n2;
+ size_t priv_read_ptr;
+
+ priv_read_ptr=atomic_read(&read_ptr);
+
+ if ((free_cnt = read_space ()) == 0) {
+ return 0;
+ }
+
+ to_read = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = priv_read_ptr + to_read;
+
+ if (cnt2 > size) {
+ n1 = size - priv_read_ptr;
+ n2 = cnt2 % size;
+ } else {
+ n1 = to_read;
+ n2 = 0;
+ }
+
+ memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
+ priv_read_ptr = (priv_read_ptr + n1) % size;
+
+ if (n2) {
+ memcpy (dest+n1, buf, n2 * sizeof (T));
+ priv_read_ptr = n2;
+ }
+
+ atomic_set(&read_ptr, priv_read_ptr);
+ return to_read;
+}
+
+template<class T> size_t
+RingBufferNPT<T>::write (T *src, size_t cnt)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t to_write;
+ size_t n1, n2;
+ size_t priv_write_ptr;
+
+ priv_write_ptr=atomic_read(&write_ptr);
+
+ if ((free_cnt = write_space ()) == 0) {
+ return 0;
+ }
+
+ to_write = cnt > free_cnt ? free_cnt : cnt;
+
+ cnt2 = priv_write_ptr + to_write;
+
+ if (cnt2 > size) {
+ n1 = size - priv_write_ptr;
+ n2 = cnt2 % size;
+ } else {
+ n1 = to_write;
+ n2 = 0;
+ }
+
+ memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
+ priv_write_ptr = (priv_write_ptr + n1) % size;
+
+ if (n2) {
+ memcpy (buf, src+n1, n2 * sizeof (T));
+ priv_write_ptr = n2;
+ }
+
+ atomic_set(&write_ptr, priv_write_ptr);
+ return to_write;
+}
+
+template<class T> void
+RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ free_cnt = w - r;
+ } else {
+ free_cnt = (w - r + size) % size;
+ }
+
+ cnt2 = r + free_cnt;
+
+ if (cnt2 > size) {
+ /* Two part vector: the rest of the buffer after the
+ current write ptr, plus some from the start of
+ the buffer.
+ */
+
+ vec->buf[0] = &buf[r];
+ vec->len[0] = size - r;
+ vec->buf[1] = buf;
+ vec->len[1] = cnt2 % size;
+
+ } else {
+
+ /* Single part vector: just the rest of the buffer */
+
+ vec->buf[0] = &buf[r];
+ vec->len[0] = free_cnt;
+ vec->len[1] = 0;
+ }
+}
+
+template<class T> void
+RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec)
+{
+ size_t free_cnt;
+ size_t cnt2;
+ size_t w, r;
+
+ w = atomic_read (&write_ptr);
+ r = atomic_read (&read_ptr);
+
+ if (w > r) {
+ free_cnt = ((r - w + size) % size) - 1;
+ } else if (w < r) {
+ free_cnt = (r - w) - 1;
+ } else {
+ free_cnt = size - 1;
+ }
+
+ cnt2 = w + free_cnt;
+
+ if (cnt2 > size) {
+
+ /* Two part vector: the rest of the buffer after the
+ current write ptr, plus some from the start of
+ the buffer.
+ */
+
+ vec->buf[0] = &buf[w];
+ vec->len[0] = size - w;
+ vec->buf[1] = buf;
+ vec->len[1] = cnt2 % size;
+ } else {
+ vec->buf[0] = &buf[w];
+ vec->len[0] = free_cnt;
+ vec->len[1] = 0;
+ }
+}
+
+#endif /* __ringbuffer_npt_h__ */
diff --git a/libs/pbd3/pbd/rt.h b/libs/pbd3/pbd/rt.h
new file mode 100644
index 0000000000..aa954fcd42
--- /dev/null
+++ b/libs/pbd3/pbd/rt.h
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+#ifndef __libmisc_rt_h__
+#define __libmisc_rt_h__
+
+extern int become_real_time_thread (int rt_priorty = 10, bool fifo = true);
+
+#endif // __libmisc_rt_h__
diff --git a/libs/pbd3/pbd/rtthread.h b/libs/pbd3/pbd/rtthread.h
new file mode 100644
index 0000000000..b99c69ba79
--- /dev/null
+++ b/libs/pbd3/pbd/rtthread.h
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+#ifndef __rtthread_h__
+#define __rtthread_h__
+
+#include <pthread.h>
+
+extern int pthread_create_realtime (pthread_t *new_thread,
+ void *(*start)(void *), void *arg,
+ int priority = 10);
+
+
+#endif // __rtthread_h__
diff --git a/libs/pbd3/pbd/scale.h b/libs/pbd3/pbd/scale.h
new file mode 100644
index 0000000000..0384ae52aa
--- /dev/null
+++ b/libs/pbd3/pbd/scale.h
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2000 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_scale_h__
+#define __pbd_scale_h__
+
+#include <cmath>
+
+inline float
+scale (float value, float lower, float upper)
+{
+ return fabs (lower + value) / (upper-lower);
+}
+
+inline float
+scale_with_range (float value, float lower, float range)
+{
+ return fabs (lower + value) / range;
+}
+
+
+inline float
+scale_to (float value, float lower, float upper, float to)
+{
+ return (fabs (lower + value) / (upper-lower)) * to;
+}
+
+inline float
+scale_to_with_range (float value, float lower, float range, float to)
+{
+ return (fabs (lower + value) / range) * to;
+}
+
+#endif /* __pbd_scale_h__ */
+
+
diff --git a/libs/pbd3/pbd/selectable.h b/libs/pbd3/pbd/selectable.h
new file mode 100644
index 0000000000..470bc3cfcc
--- /dev/null
+++ b/libs/pbd3/pbd/selectable.h
@@ -0,0 +1,102 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __selectable_h__
+#define __selectable_h__
+
+#include <list>
+#include <string>
+#include <stdio.h>
+
+#include <sigc++/sigc++.h>
+
+#include <sys/types.h>
+
+namespace Select {
+ enum Condition {
+ Readable = 0x1,
+ Writable = 0x2,
+ Exception = 0x4
+ };
+
+class Selectable : public sigc::trackable
+
+{
+ public:
+ Selectable (int fd);
+ Selectable (const std::string &, int flags, int mode = 0);
+ Selectable (FILE *);
+ ~Selectable ();
+
+ sigc::signal<void,Selectable *,Select::Condition> readable;
+ sigc::signal<void,Selectable *,Select::Condition> writable;
+ sigc::signal<void,Selectable *,Select::Condition> exceptioned;
+
+ int fd() { return _fd; }
+ bool ok() { return _ok; }
+
+ protected:
+ void selected (unsigned int condition);
+ int condition;
+ int _fd;
+
+ friend class Selector;
+
+ private:
+ enum {
+ fromFD,
+ fromPath,
+ fromFILE
+ };
+
+ bool _ok;
+ int _type;
+ std::string path;
+};
+
+class Selector {
+ private:
+ int post_select (fd_set *, fd_set *, fd_set *);
+ int _max_fd;
+
+ typedef std::list<Selectable *> Selectables;
+ Selectables selectables;
+ pthread_mutex_t list_lock;
+
+ static bool use_list_lock;
+
+ public:
+ Selector ();
+
+ void multithreaded (bool yn) {
+ use_list_lock = yn;
+ }
+
+ void add (int condition, Selectable *s);
+ void remove (Selectable *);
+ int select (unsigned long usecs);
+};
+
+
+
+} /* namespace */
+
+
+#endif // __selectable_h__
diff --git a/libs/pbd3/pbd/solaris_platform.h b/libs/pbd3/pbd/solaris_platform.h
new file mode 100644
index 0000000000..6f39a77f73
--- /dev/null
+++ b/libs/pbd3/pbd/solaris_platform.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __solaris_platform_h__
+#define __solaris_platform_h__
+
+#include <pbd/platform.h>
+
+class SolarisPlatform : public Platform
+{
+ public:
+ SolarisPlatform () : Platform () {};
+ ~SolarisPlatform () {};
+
+ int pre_config ();
+ int post_config ();
+ int pre_ui ();
+ int post_ui ();
+
+ int dsp_startup() { return 0; }
+
+};
+
+#endif // __solaris_platform_h__
diff --git a/libs/pbd3/pbd/stl_delete.h b/libs/pbd3/pbd/stl_delete.h
new file mode 100644
index 0000000000..6e5bfa0734
--- /dev/null
+++ b/libs/pbd3/pbd/stl_delete.h
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __libmisc_stl_delete_h__
+#define __libmisc_stl_delete_h__
+
+/* To actually use any of these deletion functions, you need to
+ first include the revelant container type header.
+*/
+#if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR)
+template<class T> void vector_delete (std::vector<T *> *vec)
+{
+ typename std::vector<T *>::iterator i;
+
+ for (i = vec->begin(); i != vec->end(); i++) {
+ delete *i;
+ }
+ vec->clear ();
+}
+#endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR
+
+#if defined(_CPP_MAP) || defined(_GLIBCXX_MAP) || defined(__SGI_STL_MAP)
+template<class K, class T> void map_delete (std::map<K, T *> *m)
+{
+ typename std::map<K, T *>::iterator i;
+
+ for (i = m->begin(); i != m->end(); i++) {
+ delete (*i).second;
+ }
+ m->clear ();
+}
+#endif // _CPP_MAP || _GLIBCXX_MAP || __SGI_STL_MAP
+
+#if defined(_CPP_LIST) || defined(_GLIBCXX_LIST) || defined(__SGI_STL_LIST)
+template<class T> void list_delete (std::list<T *> *l)
+{
+ typename std::list<T *>::iterator i;
+
+ for (i = l->begin(); i != l->end(); i++) {
+ delete (*i);
+ }
+
+ l->clear ();
+}
+#endif // _CPP_LIST || _GLIBCXX_LIST || __SGI_STL_LIST
+
+#if defined(_CPP_SLIST) || defined(_GLIBCXX_SLIST) || defined(__SGI_STL_SLIST)
+template<class T> void slist_delete (std::slist<T *> *l)
+{
+ typename std::slist<T *>::iterator i;
+
+ for (i = l->begin(); i != l->end(); i++) {
+ delete (*i);
+ }
+
+ l->clear ();
+}
+#endif // _CPP_SLIST || _GLIBCXX_SLIST || __SGI_STL_SLIST
+
+#if defined(_CPP_SET) || defined(_GLIBCXX_SET) || defined(__SGI_STL_SET)
+template<class T> void set_delete (std::set<T *> *sset)
+{
+ typename std::set<T *>::iterator i;
+
+ for (i = sset->begin(); i != sset->end(); i++) {
+ delete *i;
+ }
+ sset->erase (sset->begin(), sset->end());
+}
+#endif // _CPP_SET || _GLIBCXX_SET || __SGI_STL_SET
+
+#endif // __libmisc_stl_delete_h__
diff --git a/libs/pbd3/pbd/stl_functors.h b/libs/pbd3/pbd/stl_functors.h
new file mode 100644
index 0000000000..4a96e91a28
--- /dev/null
+++ b/libs/pbd3/pbd/stl_functors.h
@@ -0,0 +1,93 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __stl_functors_h__
+#define __stl_functors_h__
+
+#include <string>
+
+#ifndef LESS_STRING_P
+struct less<std::string *> {
+ bool operator()(std::string *s1, std::string *s2) const {
+ return *s1 < *s2;
+ }
+};
+#define LESS_STRING_P
+#endif // LESS_STRING_P
+
+#ifndef LESS_CONST_STRING_P
+struct less<const std::string *> {
+ bool operator()(const std::string *s1, const std::string *s2) const {
+ return *s1 < *s2;
+ }
+};
+#define LESS_CONST_STRING_P
+#endif // LESS_CONST_STRING_P
+
+#ifndef LESS_CONST_CHAR_P
+struct less<const char *>
+{
+ bool operator()(const char* s1, const char* s2) const {
+ return strcmp(s1, s2) < 0;
+ }
+};
+#define LESS_CONST_CHAR_P
+#endif // LESS_CONST_CHAR_P
+
+#ifndef LESS_CONST_FLOAT_P
+struct less<const float *>
+{
+ bool operator()(const float *n1, const float *n2) const {
+ return *n1 < *n2;
+ }
+};
+#define LESS_CONST_FLOAT_P
+#endif // LESS_CONST_FLOAT_P
+
+#ifndef EQUAL_TO_CONST_CHAR_P
+struct equal_to<const char *>
+{
+ bool operator()(const char *s1, const char *s2) const {
+ return strcmp (s1, s2) == 0;
+ }
+};
+#define EQUAL_TO_CONST_CHAR_P
+#endif // EQUAL_TO_CONST_CHAR_P
+
+#ifndef EQUAL_TO_STRING_P
+struct equal_to<std::string *>
+{
+ bool operator()(const std::string *s1, const std::string *s2) const {
+ return *s1 == *s2;
+ }
+};
+#define EQUAL_TO_STRING_P
+#endif // EQUAL_TO_STRING_P
+
+#ifndef LESS_CONST_STRING_R
+struct less<const std::string &> {
+ bool operator() (const std::string &s1, const std::string &s2) {
+ return s1 < s2;
+ }
+};
+#define LESS_CONST_STRING_R
+#endif // EQUAL_TO_STRING_P
+
+#endif // __stl_functors_h__
diff --git a/libs/pbd3/pbd/strsplit.h b/libs/pbd3/pbd/strsplit.h
new file mode 100644
index 0000000000..e55ad1c825
--- /dev/null
+++ b/libs/pbd3/pbd/strsplit.h
@@ -0,0 +1,9 @@
+#ifndef __pbd_strplit_h__
+#define __pbd_strplit_h__
+
+#include <string>
+#include <vector>
+
+extern void split (std::string, std::vector<std::string>&, char);
+
+#endif // __pbd_strplit_h__
diff --git a/libs/pbd3/pbd/strsub.h b/libs/pbd3/pbd/strsub.h
new file mode 100644
index 0000000000..c5bfb1ade4
--- /dev/null
+++ b/libs/pbd3/pbd/strsub.h
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __libmisc_strsub_h__
+#define __libmisc_strsub_h__
+
+extern char *strsub (char *str, const char *target, const char *replacement);
+
+#endif // __libmisc_strsub_h__
diff --git a/libs/pbd3/pbd/textreceiver.h b/libs/pbd3/pbd/textreceiver.h
new file mode 100644
index 0000000000..b8bfe5bc78
--- /dev/null
+++ b/libs/pbd3/pbd/textreceiver.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __libmisc_textreceiver_h__
+#define __libmisc_textreceiver_h__
+
+#include <string>
+
+#include "receiver.h"
+
+using std::string;
+using std::cout;
+using std::endl;
+
+class TextReceiver : public Receiver
+{
+ public:
+ TextReceiver (const string &n);
+
+ protected:
+ void receive (Transmitter::Channel, const char *);
+
+ private:
+ string name;
+};
+
+#endif //__libmisc_textreceiver_h__
diff --git a/libs/pbd3/pbd/thread.h b/libs/pbd3/pbd/thread.h
new file mode 100644
index 0000000000..c1d5c3c78d
--- /dev/null
+++ b/libs/pbd3/pbd/thread.h
@@ -0,0 +1,127 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __qm_thread_h__
+#define __qm_thread_h__
+
+#include <pthread.h>
+
+/* A generic base class for Quasimodo objects requiring their own
+ thread to do work.
+*/
+
+class QMThread
+
+{
+ public:
+ QMThread (const char *name,
+ void *(start)(void *), void *,
+ bool realtime = false, int rt_priority = 10);
+
+ virtual ~QMThread();
+
+ int run ();
+ void poke ();
+ void pause ();
+ void stop ();
+ void *wait ();
+
+ /* This doesn't guarantee anything about the state of
+ the thread, but if you do things the right way, and
+ make sure that the do_work() routine checks
+ work_no_more() at the right times, and that the
+ thread is awake, then calling this will cause
+ the thread to exit fairly quickly.
+ */
+
+ void halt() { _must_exit = true ; }
+
+ void exit (void *status);
+ pthread_t thread_id() { return _thread; }
+
+ bool thread_ok () { return _have_thread; }
+ bool thread_active() { return _thread_active; }
+
+ bool thread_running () {
+ /* XXX not atomic */
+ return _running && _thread_active;
+ }
+
+ bool thread_waiting () { return _thread_waiting; }
+
+ static void try_to_kill_all_threads() {
+ all_threads_must_die = true;
+ }
+
+ protected:
+ void *main ();
+
+ bool work_no_more () { return (!_running || _must_exit || all_threads_must_die); }
+
+ bool myself () {
+ return pthread_equal (_thread, pthread_self());
+ }
+
+ void suspend() {
+ _running = false;
+ }
+
+ void lock (pthread_mutex_t *lock) {
+ pthread_mutex_lock (lock);
+ }
+
+ void unlock (pthread_mutex_t *lock) {
+ pthread_mutex_unlock (lock);
+ }
+
+ virtual void *do_work () = 0;
+
+ private:
+ const char *_name;
+ bool _must_exit;
+ bool _running;
+ bool _thread_active;
+ bool _thread_waiting;
+ bool _have_thread;
+
+ size_t work_cnt;
+
+ pthread_mutex_t status_lock;
+ pthread_cond_t wake_up; /* protected by status_lock */
+ pthread_cond_t asleep; /* protected by status_lock */
+ pthread_cond_t running; /* protected by status_lock */
+ pthread_cond_t exited; /* protected by status_lock */
+ pthread_t _thread;
+
+ void lock () {
+ pthread_mutex_lock (&status_lock);
+ }
+
+ void unlock () {
+ pthread_mutex_unlock (&status_lock);
+ }
+
+ static bool all_threads_must_die;
+
+ static void signal_catcher (int sig);
+ void setup_signals ();
+};
+
+#endif // __qm_thread_h__
diff --git a/libs/pbd3/pbd/thrown_error.h b/libs/pbd3/pbd/thrown_error.h
new file mode 100644
index 0000000000..83cf8acfac
--- /dev/null
+++ b/libs/pbd3/pbd/thrown_error.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+#ifndef __qm_thrown_error_h__
+#define __qm_thrown_error_h__
+
+#include "transmitter.h"
+
+#define SAFE_THROW(T) \
+ T *sent = new T; \
+ (*sent) << rdbuf(); \
+ throw sent
+
+class ThrownError : public Transmitter {
+ public:
+ ThrownError () : Transmitter (Transmitter::Throw) {}
+ protected:
+ virtual void deliver () = 0;
+};
+
+#endif // __qm_thrown_error_h__
+
+
diff --git a/libs/pbd3/pbd/touchable.h b/libs/pbd3/pbd/touchable.h
new file mode 100644
index 0000000000..0298574dfa
--- /dev/null
+++ b/libs/pbd3/pbd/touchable.h
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_touchable_h__
+#define __pbd_touchable_h__
+
+class Touchable
+{
+ public:
+ Touchable() : _delete_after_touch (false) {}
+ virtual ~Touchable() {}
+
+ void set_delete_after_touch (bool yn) { _delete_after_touch = yn; }
+ bool delete_after_touch() const { return _delete_after_touch; }
+
+ virtual void touch () = 0;
+
+ protected:
+ bool _delete_after_touch;
+};
+
+template<class T>
+class DynamicTouchable : public Touchable
+{
+ public:
+ DynamicTouchable (T& t, void (T::*m)(void))
+ : object (t), method (m) { set_delete_after_touch (true); }
+
+ void touch () {
+ (object.*method)();
+ }
+
+ protected:
+ T& object;
+ void (T::*method)(void);
+};
+
+template<class T1, class T2>
+class DynamicTouchable1 : public Touchable
+{
+ public:
+ DynamicTouchable1 (T1& t, void (T1::*m)(T2), T2 a)
+ : object (t), method (m), arg (a) { set_delete_after_touch (true); }
+
+ void touch () {
+ (object.*method)(arg);
+ }
+
+ protected:
+ T1& object;
+ void (T1::*method)(T2);
+ T2 arg;
+};
+
+template<class T1, class T2, class T3>
+class DynamicTouchable2 : public Touchable
+{
+ public:
+ DynamicTouchable2 (T1& t, void (T1::*m)(T2, T3), T2 a1, T3 a2)
+ : object (t), method (m), arg1 (a1), arg2 (a2) { set_delete_after_touch (true); }
+
+ void touch () {
+ (object.*method)(arg1, arg2);
+ }
+
+ protected:
+ T1& object;
+ void (T1::*method)(T2,T3);
+ T2 arg1;
+ T3 arg2;
+};
+
+#endif // __pbd_touchable_h__
diff --git a/libs/pbd3/pbd/transmitter.h b/libs/pbd3/pbd/transmitter.h
new file mode 100644
index 0000000000..07fc266bce
--- /dev/null
+++ b/libs/pbd3/pbd/transmitter.h
@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __libmisc_transmitter_h__
+#define __libmisc_transmitter_h__
+
+#include <sstream>
+#include <iostream>
+
+#include <sigc++/sigc++.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+
+class Transmitter : public std::stringstream
+
+{
+ public:
+ enum Channel {
+ Info,
+ Error,
+ Warning,
+ Fatal,
+ Throw
+ };
+
+ Transmitter (Channel);
+
+ sigc::signal<void,Channel, const char *> &sender() {
+ return *send;
+ }
+
+ bool does_not_return ();
+
+ protected:
+ virtual void deliver ();
+ friend std::ostream& endmsg (std::ostream &);
+
+ private:
+ Channel channel;
+ sigc::signal<void, Channel, const char *> *send;
+
+ sigc::signal<void, Channel, const char *> info;
+ sigc::signal<void, Channel, const char *> warning;
+ sigc::signal<void, Channel, const char *> error;
+ sigc::signal<void, Channel, const char *> fatal;
+};
+
+/* for EGCS 2.91.66, if this function is not compiled within the same
+ compilation unit as the one where a ThrownError is thrown, then
+ nothing will catch the error. This is a pretty small function, so
+ inlining it here seems like a reasonable workaround.
+*/
+
+inline std::ostream &
+endmsg (std::ostream &ostr)
+
+{
+ Transmitter *t;
+
+ /* There is a serious bug in the Cygnus/GCC libstdc++ library:
+ cout is not actually an ostream, but a trick was played
+ to make the compiler think that it is. This will cause
+ the dynamic_cast<> to fail with SEGV. So, first check to
+ see if ostr == cout, and handle it specially.
+ */
+
+ if (&ostr == &cout) {
+ cout << endl;
+ return ostr;
+ } else if (&ostr == &cerr) {
+ cerr << endl;
+ return ostr;
+ }
+
+ if ((t = dynamic_cast<Transmitter *> (&ostr)) != 0) {
+ t->deliver ();
+ } else {
+ /* hmm. not a Transmitter, so just put a newline on
+ it and assume that that will be enough.
+ */
+
+ ostr << endl;
+ }
+
+ return ostr;
+}
+
+extern "C" { void pbd_c_error (const char *); }
+
+#endif // __libmisc_transmitter_h__
diff --git a/libs/pbd3/pbd/types.h b/libs/pbd3/pbd/types.h
new file mode 100644
index 0000000000..52f067fd04
--- /dev/null
+++ b/libs/pbd3/pbd/types.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __pbd_types_h__
+#define __pbd_types_h__
+
+typedef unsigned char byte;
+typedef char int8;
+typedef unsigned short uint16;
+typedef short int16;
+typedef unsigned int uint32;
+typedef int int32;
+typedef unsigned long long int uint64;
+typedef long long int int64;
+
+#endif // __pbd_types_h__
diff --git a/libs/pbd3/pbd/undo.h b/libs/pbd3/pbd/undo.h
new file mode 100644
index 0000000000..f067635ed3
--- /dev/null
+++ b/libs/pbd3/pbd/undo.h
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2002 Brett Viren & Paul Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __lib_pbd_undo_h__
+#define __lib_pbd_undo_h__
+
+#include <string>
+#include <list>
+#include <sigc++/slot.h>
+#include <sys/time.h>
+
+using std::string;
+using std::list;
+
+typedef sigc::slot<void> UndoAction;
+
+class UndoCommand
+{
+ public:
+ UndoCommand ();
+ UndoCommand (const UndoCommand&);
+ UndoCommand& operator= (const UndoCommand&);
+
+ void clear ();
+
+ void add_undo (const UndoAction&);
+ void add_redo (const UndoAction&);
+ void add_redo_no_execute (const UndoAction&);
+
+ void undo();
+ void redo();
+
+ void set_name (const string& str) {
+ _name = str;
+ }
+ const string& name() const { return _name; }
+
+ void set_timestamp (struct timeval &t) {
+ _timestamp = t;
+ }
+
+ const struct timeval& timestamp() const {
+ return _timestamp;
+ }
+
+ private:
+ list<UndoAction> redo_actions;
+ list<UndoAction> undo_actions;
+ struct timeval _timestamp;
+ string _name;
+};
+
+class UndoHistory
+{
+ public:
+ UndoHistory() {}
+ ~UndoHistory() {}
+
+ void add (UndoCommand uc);
+ void undo (unsigned int n);
+ void redo (unsigned int n);
+
+ unsigned long undo_depth() const { return UndoList.size(); }
+ unsigned long redo_depth() const { return RedoList.size(); }
+
+ string next_undo() const { return (UndoList.empty() ? string("") : UndoList.back().name()); }
+ string next_redo() const { return (RedoList.empty() ? string("") : RedoList.back().name()); }
+
+ void clear ();
+ void clear_undo ();
+ void clear_redo ();
+
+ private:
+ list<UndoCommand> UndoList;
+ list<UndoCommand> RedoList;
+};
+
+
+#endif /* __lib_pbd_undo_h__ */
diff --git a/libs/pbd3/pbd/unescape.h b/libs/pbd3/pbd/unescape.h
new file mode 100644
index 0000000000..6596a86113
--- /dev/null
+++ b/libs/pbd3/pbd/unescape.h
@@ -0,0 +1,6 @@
+#ifndef __unescape_h__
+#define __unescape_h__
+
+void unescape (char *);
+
+#endif // __unescape_h__
diff --git a/libs/pbd3/pbd/xml++.h b/libs/pbd3/pbd/xml++.h
new file mode 100644
index 0000000000..993cb22fdf
--- /dev/null
+++ b/libs/pbd3/pbd/xml++.h
@@ -0,0 +1,127 @@
+/* xml++.h
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#include <string>
+#include <list>
+#include <map>
+#include <cstdio>
+#include <cstdarg>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#ifndef __XML_H
+#define __XML_H
+
+using std::string;
+using std::map;
+using std::list;
+
+class XMLTree;
+class XMLNode;
+class XMLProperty;
+
+typedef list<XMLNode *> XMLNodeList;
+typedef XMLNodeList::iterator XMLNodeIterator;
+typedef XMLNodeList::const_iterator XMLNodeConstIterator;
+typedef list<XMLProperty*> XMLPropertyList;
+typedef XMLPropertyList::iterator XMLPropertyIterator;
+typedef XMLPropertyList::const_iterator XMLPropertyConstIterator;
+typedef map<string, XMLProperty*> XMLPropertyMap;
+
+class XMLTree {
+private:
+ string _filename;
+ XMLNode *_root;
+ int _compression;
+ bool _initialized;
+
+public:
+ XMLTree();
+ XMLTree(const string &fn);
+ XMLTree(const XMLTree *);
+ ~XMLTree();
+
+ bool initialized() const { return _initialized; };
+ XMLNode *root() const { return _root; };
+ XMLNode *set_root(XMLNode *n) { return _root = n; };
+
+ const string & filename() const { return _filename; };
+ const string & set_filename(const string &fn) { return _filename = fn; };
+
+ int compression() const { return _compression; };
+ int set_compression(int);
+
+ bool read();
+ bool read(const string &fn) { set_filename(fn); return read(); };
+ bool read_buffer(const string &);
+
+ bool write() const;
+ bool write(const string &fn) { set_filename(fn); return write(); };
+
+ void debug (FILE*) const;
+
+ const string & write_buffer() const;
+};
+
+class XMLNode {
+private:
+ bool _initialized;
+ string _name;
+ bool _is_content;
+ string _content;
+ XMLNodeList _children;
+ XMLPropertyList _proplist;
+ XMLPropertyMap _propmap;
+
+public:
+ XMLNode(const string &);
+ XMLNode(const string &, const string &);
+ XMLNode(const XMLNode&);
+ ~XMLNode();
+
+ bool initialized() const { return _initialized; };
+ const string name() const { return _name; };
+
+ bool is_content() const { return _is_content; };
+ const string & content() const { return _content; };
+ const string & set_content(const string &);
+ XMLNode *add_content(const string & = string());
+
+ const XMLNodeList & children(const string & = string()) const;
+ XMLNode *add_child(const string &);
+ XMLNode *add_child_copy(const XMLNode&);
+ void add_child_nocopy (XMLNode&);
+
+ const XMLPropertyList & properties() const { return _proplist; };
+ XMLProperty *property(const string &);
+ const XMLProperty *property(const string &n) const
+ { return ((XMLNode *) this)->property(n); };
+ XMLProperty *add_property(const string &, const string & = string());
+ void remove_property(const string &);
+
+ /** Remove all nodes with the name passed to remove_nodes */
+ void remove_nodes(const string &);
+ /** Remove and delete all nodes with the name passed to remove_nodes */
+ void remove_nodes_and_delete(const string &);
+};
+
+class XMLProperty {
+private:
+ string _name;
+ string _value;
+
+public:
+ XMLProperty(const string &n, const string &v = string());
+ ~XMLProperty();
+
+ const string & name() const { return _name; };
+ const string & value() const { return _value; };
+ const string & set_value(const string &v) { return _value = v; };
+};
+
+#endif /* __XML_H */
+
diff --git a/libs/pbd3/pool.cc b/libs/pbd3/pool.cc
new file mode 100644
index 0000000000..f05d88381c
--- /dev/null
+++ b/libs/pbd3/pool.cc
@@ -0,0 +1,135 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <iostream>
+#include <sys/mman.h>
+#include <vector>
+
+#include <pbd/pool.h>
+#include <pbd/error.h>
+#include <pbd/stl_delete.h>
+#include <pbd/pthread_utils.h>
+
+using namespace std;
+
+Pool::Pool (string n, unsigned long item_size, unsigned long nitems)
+{
+ _name = n;
+
+ free_list = new RingBuffer<void*> (nitems);
+
+ /* since some overloaded ::operator new() might use this,
+ its important that we use a "lower level" allocator to
+ get more space.
+ */
+
+ block = malloc (nitems * item_size);
+
+ void **ptrlist = (void **) malloc (sizeof (void *) * nitems);
+
+ for (unsigned long i = 0; i < nitems; i++) {
+ ptrlist[i] = static_cast<void *> (static_cast<char*>(block) + (i * item_size));
+ }
+
+ free_list->write (ptrlist, nitems);
+
+ free (ptrlist);
+}
+
+Pool::~Pool ()
+{
+ free (block);
+}
+
+void *
+Pool::alloc ()
+{
+ void *ptr;
+
+// cerr << _name << " pool " << " alloc, thread = " << pthread_name() << " space = " << free_list->read_space() << endl;
+
+ if (free_list->read (&ptr, 1) < 1) {
+ fatal << "CRITICAL: " << _name << " POOL OUT OF MEMORY - RECOMPILE WITH LARGER SIZE!!" << endmsg;
+ /*NOTREACHED*/
+ return 0;
+ } else {
+ return ptr;
+ }
+};
+
+void
+Pool::release (void *ptr)
+{
+ free_list->write (&ptr, 1);
+// cerr << _name << ": release, now has " << free_list->read_space() << endl;
+}
+
+/*---------------------------------------------*/
+
+MultiAllocSingleReleasePool::MultiAllocSingleReleasePool (string n, unsigned long isize, unsigned long nitems)
+ : Pool (n, isize, nitems)
+{
+ pthread_mutex_init (&lock, 0);
+}
+
+MultiAllocSingleReleasePool::~MultiAllocSingleReleasePool ()
+{
+}
+
+SingleAllocMultiReleasePool::SingleAllocMultiReleasePool (string n, unsigned long isize, unsigned long nitems)
+ : Pool (n, isize, nitems)
+{
+ pthread_mutex_init (&lock, 0);
+}
+
+SingleAllocMultiReleasePool::~SingleAllocMultiReleasePool ()
+{
+}
+
+void*
+MultiAllocSingleReleasePool::alloc ()
+{
+ void *ptr;
+ pthread_mutex_lock (&lock);
+ ptr = Pool::alloc ();
+ pthread_mutex_unlock (&lock);
+ return ptr;
+}
+
+void
+MultiAllocSingleReleasePool::release (void* ptr)
+{
+ Pool::release (ptr);
+}
+
+void*
+SingleAllocMultiReleasePool::alloc ()
+{
+ return Pool::alloc ();
+}
+
+void
+SingleAllocMultiReleasePool::release (void* ptr)
+{
+ pthread_mutex_lock (&lock);
+ Pool::release (ptr);
+ pthread_mutex_unlock (&lock);
+}
+
diff --git a/libs/pbd3/pthread_utils.cc b/libs/pbd3/pthread_utils.cc
new file mode 100644
index 0000000000..6ef29e3605
--- /dev/null
+++ b/libs/pbd3/pthread_utils.cc
@@ -0,0 +1,133 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <map>
+#include <iostream>
+#include <string>
+
+#include <pbd/pthread_utils.h>
+
+using std::string;
+using std::cerr;
+using std::endl;
+
+typedef std::map<string,pthread_t> ThreadMap;
+static ThreadMap all_threads;
+static pthread_mutex_t thread_map_lock = PTHREAD_MUTEX_INITIALIZER;
+
+namespace PBD {
+ sigc::signal<void,pthread_t,std::string> ThreadCreated;
+}
+
+using namespace PBD;
+
+int
+pthread_create_and_store (string name, pthread_t *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg)
+{
+ int ret;
+
+ if ((ret = pthread_create (thread, attr, start_routine, arg)) == 0) {
+ std::pair<string,pthread_t> newpair;
+ newpair.first = name;
+ newpair.second = *thread;
+
+ pthread_mutex_lock (&thread_map_lock);
+ all_threads.insert (newpair);
+
+ pthread_mutex_unlock (&thread_map_lock);
+ }
+
+ return ret;
+}
+
+string
+pthread_name ()
+{
+ pthread_t self = pthread_self();
+ string str;
+
+ pthread_mutex_lock (&thread_map_lock);
+ for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+ if (i->second == self) {
+ str = i->first;
+ pthread_mutex_unlock (&thread_map_lock);
+ return str;
+ }
+ }
+ pthread_mutex_unlock (&thread_map_lock);
+ return "unknown";
+}
+
+void
+pthread_kill_all (int signum)
+{
+ pthread_mutex_lock (&thread_map_lock);
+ for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+ if (i->second != pthread_self()) {
+ pthread_kill (i->second, signum);
+ }
+ }
+ all_threads.clear();
+ pthread_mutex_unlock (&thread_map_lock);
+}
+
+void
+pthread_cancel_all ()
+{
+ pthread_mutex_lock (&thread_map_lock);
+ for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+ if (i->second != pthread_self()) {
+ pthread_cancel (i->second);
+ }
+ }
+ all_threads.clear();
+ pthread_mutex_unlock (&thread_map_lock);
+}
+
+void
+pthread_cancel_one (pthread_t thread)
+{
+ pthread_mutex_lock (&thread_map_lock);
+ for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+ if (i->second == thread) {
+ all_threads.erase (i);
+ break;
+ }
+ }
+
+ pthread_cancel (thread);
+ pthread_mutex_unlock (&thread_map_lock);
+}
+
+void
+pthread_exit_pbd (void* status)
+{
+ pthread_t thread = pthread_self();
+
+ pthread_mutex_lock (&thread_map_lock);
+ for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+ if (i->second == thread) {
+ all_threads.erase (i);
+ break;
+ }
+ }
+ pthread_mutex_unlock (&thread_map_lock);
+ pthread_exit (status);
+}
diff --git a/libs/pbd3/receiver.cc b/libs/pbd3/receiver.cc
new file mode 100644
index 0000000000..5e7c10de70
--- /dev/null
+++ b/libs/pbd3/receiver.cc
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <vector>
+
+#include <pbd/receiver.h>
+#include <pbd/transmitter.h>
+
+using namespace sigc;
+
+Receiver::Receiver () {}
+
+Receiver::~Receiver ()
+
+{
+ hangup ();
+}
+
+void
+Receiver::hangup ()
+{
+ vector<sigc::connection *>::iterator i;
+
+ for (i = connections.begin(); i != connections.end (); i++) {
+ (*i)->disconnect ();
+ delete *i;
+ }
+
+ connections.erase (connections.begin(), connections.end());
+}
+
+void
+Receiver::listen_to (Transmitter &transmitter)
+
+{
+ sigc::connection *c = new sigc::connection;
+
+ (*c) = transmitter.sender().connect(mem_fun(*this, &Receiver::receive));
+
+ connections.push_back (c);
+}
diff --git a/libs/pbd3/strsplit.cc b/libs/pbd3/strsplit.cc
new file mode 100644
index 0000000000..7f29a77887
--- /dev/null
+++ b/libs/pbd3/strsplit.cc
@@ -0,0 +1,41 @@
+#include <pbd/strsplit.h>
+
+using namespace std;
+
+void
+split (string str, vector<string>& result, char splitchar)
+{
+ string::size_type pos;
+ string remaining;
+ string::size_type len = str.length();
+ int cnt;
+
+ cnt = 0;
+
+ if (str.empty()) {
+ return;
+ }
+
+ for (string::size_type n = 0; n < len; ++n) {
+ if (str[n] == splitchar) {
+ cnt++;
+ }
+ }
+
+ if (cnt == 0) {
+ result.push_back (str);
+ return;
+ }
+
+ remaining = str;
+
+ while ((pos = remaining.find_first_of (':')) != string::npos) {
+ result.push_back (remaining.substr (0, pos));
+ remaining = remaining.substr (pos+1);
+ }
+
+ if (remaining.length()) {
+
+ result.push_back (remaining);
+ }
+}
diff --git a/libs/pbd3/textreceiver.cc b/libs/pbd3/textreceiver.cc
new file mode 100644
index 0000000000..43620e9830
--- /dev/null
+++ b/libs/pbd3/textreceiver.cc
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <iostream>
+#include <cstdlib>
+
+#include <pbd/textreceiver.h>
+
+TextReceiver::TextReceiver (const string &n)
+
+{
+ name = n;
+}
+
+void
+TextReceiver::receive (Transmitter::Channel chn, const char *str)
+
+{
+ const char *prefix = "";
+
+ switch (chn) {
+ case Transmitter::Error:
+ prefix = ": [ERROR]: ";
+ break;
+ case Transmitter::Info:
+ prefix = ": [INFO]: ";
+ break;
+ case Transmitter::Warning:
+ prefix = ": [WARNING]: ";
+ break;
+ case Transmitter::Fatal:
+ prefix = ": [FATAL]: ";
+ break;
+ case Transmitter::Throw:
+ /* this isn't supposed to happen */
+ abort ();
+ }
+
+ /* note: iostreams are already thread-safe: no external
+ lock required.
+ */
+
+ cout << name << prefix << str << endl;
+
+ if (chn == Transmitter::Fatal) {
+ exit (9);
+ }
+}
+
diff --git a/libs/pbd3/transmitter.cc b/libs/pbd3/transmitter.cc
new file mode 100644
index 0000000000..09823a7991
--- /dev/null
+++ b/libs/pbd3/transmitter.cc
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 1998-99 Paul Barton-Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <signal.h>
+#include <iostream>
+#include <string>
+
+#include <pbd/transmitter.h>
+
+using std::string;
+using std::ios;
+
+Transmitter::Transmitter (Channel c)
+
+{
+ channel = c;
+ switch (c) {
+ case Error:
+ send = &error;
+ break;
+ case Warning:
+ send = &warning;
+ break;
+ case Info:
+ send = &info;
+ break;
+ case Fatal:
+ send = &fatal;
+ break;
+ case Throw:
+ /* we should never call Transmitter::deliver
+ for thrown messages (because its overridden in the
+ class heirarchy). force a segv if we do.
+ */
+ send = 0;
+ break;
+ }
+}
+
+void
+Transmitter::deliver ()
+
+{
+ string foo;
+
+ /* NOTE: this is just a default action for a Transmitter or a
+ derived class. Any class can override this to produce some
+ other action when deliver() is called.
+ */
+
+ *this << '\0';
+
+ /* send the SigC++ signal */
+
+ foo = str();
+ (*send) (channel, foo.c_str());
+
+ /* XXX when or how can we delete this ? */
+ // delete foo;
+
+ /* return to a pristine state */
+
+ clear ();
+ seekp (0, ios::beg);
+ seekg (0, ios::beg);
+
+ /* do the right thing if this should not return */
+
+ if (does_not_return()) {
+ sigset_t mask;
+
+ sigemptyset (&mask);
+ sigsuspend (&mask);
+ /*NOTREACHED*/
+ exit (1);
+ }
+}
+
+bool
+Transmitter::does_not_return ()
+
+{
+ if (channel == Fatal || channel == Throw) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+extern "C" {
+ void pbd_c_error (const char *str)
+
+ {
+ extern Transmitter error;
+ error << str << endmsg;
+ }
+}
diff --git a/libs/pbd3/undo.cc b/libs/pbd3/undo.cc
new file mode 100644
index 0000000000..0af1cc2e7a
--- /dev/null
+++ b/libs/pbd3/undo.cc
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2001 Brett Viren & Paul Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <iostream>
+
+#include <pbd/undo.h>
+
+using namespace std;
+using namespace sigc;
+
+UndoCommand::UndoCommand ()
+{
+}
+
+UndoCommand::UndoCommand (const UndoCommand& rhs)
+{
+ _name = rhs._name;
+ clear ();
+ undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end());
+ redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end());
+}
+
+UndoCommand&
+UndoCommand::operator= (const UndoCommand& rhs)
+{
+ if (this == &rhs) return *this;
+ _name = rhs._name;
+ clear ();
+ undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end());
+ redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end());
+ return *this;
+}
+
+void
+UndoCommand::add_undo (const UndoAction& action)
+{
+ undo_actions.push_back (action);
+}
+
+void
+UndoCommand::add_redo (const UndoAction& action)
+{
+ redo_actions.push_back (action);
+ redo_actions.back()(); // operator()
+}
+
+void
+UndoCommand::add_redo_no_execute (const UndoAction& action)
+{
+ redo_actions.push_back (action);
+}
+
+void
+UndoCommand::clear ()
+{
+ undo_actions.clear ();
+ redo_actions.clear ();
+}
+
+void
+UndoCommand::undo ()
+{
+ for (list<UndoAction>::reverse_iterator i = undo_actions.rbegin(); i != undo_actions.rend(); ++i) {
+ (*i)();
+ }
+}
+
+void
+UndoCommand::redo ()
+{
+ for (list<UndoAction>::iterator i = redo_actions.begin(); i != redo_actions.end(); ++i) {
+ (*i)();
+ }
+}
+
+void
+UndoHistory::add (UndoCommand uc)
+{
+ UndoList.push_back (uc);
+}
+
+void
+UndoHistory::undo (unsigned int n)
+{
+ while (n--) {
+ if (UndoList.size() == 0) {
+ return;
+ }
+ UndoCommand uc = UndoList.back ();
+ UndoList.pop_back ();
+ uc.undo ();
+ RedoList.push_back (uc);
+ }
+}
+
+void
+UndoHistory::redo (unsigned int n)
+{
+ while (n--) {
+ if (RedoList.size() == 0) {
+ return;
+ }
+ UndoCommand cmd = RedoList.back ();
+ RedoList.pop_back ();
+ cmd.redo ();
+ UndoList.push_back (cmd);
+ }
+}
+
+void
+UndoHistory::clear_redo ()
+{
+ RedoList.clear ();
+}
+
+void
+UndoHistory::clear_undo ()
+{
+ UndoList.clear ();
+}
+
+void
+UndoHistory::clear ()
+{
+ RedoList.clear ();
+ UndoList.clear ();
+}
diff --git a/libs/pbd3/unescape.cc b/libs/pbd3/unescape.cc
new file mode 100644
index 0000000000..2c79740e4a
--- /dev/null
+++ b/libs/pbd3/unescape.cc
@@ -0,0 +1,137 @@
+#include <cstdlib>
+
+#include <pbd/unescape.h>
+
+void
+unescape (char *str)
+
+{
+ char *p;
+ bool escaped;
+ long offset;
+ char octal[4];
+ int noct;
+ char hex[3];
+ int nhex;
+
+ escaped = false;
+ offset = 0;
+ octal[3] = '\0';
+ hex[2] = '\0';
+
+ p = str;
+
+ while (*p) {
+ if (!escaped) {
+ if (*p == '\\') {
+ escaped = true;
+ } else {
+ *(p-offset) = *p;
+ }
+ p++;
+ continue;
+ }
+
+ switch (*p) {
+ case 'f':
+ offset++;
+ *(p-offset) = '\f';
+ break;
+ case 'r':
+ offset++;
+ *(p-offset) = '\r';
+ break;
+
+ case 'v':
+ offset++;
+ *(p-offset) = '\v';
+ break;
+
+ case 'n':
+ offset++;
+ *(p-offset) = '\n';
+ break;
+
+ case 't':
+ offset++;
+ *(p-offset) = '\t';
+ break;
+
+ case 'b':
+ offset++;
+ *(p-offset) = '\b';
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ noct = 0;
+ while (noct < 3 &&
+ (*p >= '0' && *p <= '7')) {
+ octal[noct++] = *p;
+ offset++;
+ p++;
+ }
+ p--;
+ *(p-offset) = strtol (octal, 0, 8);
+ break;
+
+ case 'x':
+ nhex = 0;
+ p++;
+ offset++;
+
+ while (nhex < 2 &&
+ ((*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'f') ||
+ (*p >= 'A' && *p <= 'F'))) {
+ hex[nhex++] = *p;
+ offset++;
+ p++;
+ }
+ p--;
+ *(p-offset) = strtol (hex, 0, 16);
+ break;
+
+ case '\\':
+ offset++;
+ *(p-offset) = '\\';
+ break;
+
+ case '"':
+ offset++;
+ *(p-offset) = '"';
+ break;
+
+ case '\'':
+ offset++;
+ *(p-offset) = '\'';
+ break;
+
+ default:
+ *(p-offset) = *p;
+ }
+
+ escaped = false;
+ p++;
+ }
+
+ *(p-offset) = '\0';
+}
+
+#ifdef TEST
+#include <cstdio>
+
+main (int argc, char *argv[])
+
+{
+ unescape (argv[1]);
+ printf ("%s\n", argv[1]);
+}
+
+#endif
diff --git a/libs/pbd3/xml++.cc b/libs/pbd3/xml++.cc
new file mode 100644
index 0000000000..2dbf2a861f
--- /dev/null
+++ b/libs/pbd3/xml++.cc
@@ -0,0 +1,416 @@
+/* xml++.cc
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#include <pbd/xml++.h>
+#include <libxml/debugXML.h>
+
+static XMLNode *readnode(xmlNodePtr);
+static void writenode(xmlDocPtr, XMLNode *, xmlNodePtr, int);
+
+XMLTree::XMLTree()
+ : _filename(),
+ _root(),
+ _compression(0),
+ _initialized(false)
+{
+}
+
+XMLTree::XMLTree(const string &fn)
+ : _filename(fn),
+ _root(0),
+ _compression(0),
+ _initialized(false)
+{
+ read();
+}
+
+XMLTree::XMLTree(const XMLTree * from)
+{
+ _filename = from->filename();
+ _root = new XMLNode(*from->root());
+ _compression = from->compression();
+ _initialized = true;
+}
+
+XMLTree::~XMLTree()
+{
+ if (_initialized && _root)
+ delete _root;
+}
+
+int
+XMLTree::set_compression(int c)
+{
+ if (c > 9)
+ c = 9;
+
+ if (c < 0)
+ c = 0;
+
+ _compression = c;
+
+ return _compression;
+}
+
+bool
+XMLTree::read(void)
+{
+ xmlDocPtr doc;
+
+ if (_root) {
+ delete _root;
+ _root = 0;
+ }
+
+ xmlKeepBlanksDefault(0);
+
+ doc = xmlParseFile(_filename.c_str());
+ if (!doc) {
+ _initialized = false;
+ return false;
+ }
+
+ _root = readnode(xmlDocGetRootElement(doc));
+ xmlFreeDoc(doc);
+ _initialized = true;
+
+ return true;
+}
+
+bool
+XMLTree::read_buffer(const string & buffer)
+{
+ xmlDocPtr doc;
+
+ _filename = "";
+
+ if (_root) {
+ delete _root;
+ _root = 0;
+ }
+
+ doc = xmlParseMemory((char *) buffer.c_str(), buffer.length());
+ if (!doc) {
+ _initialized = false;
+ return false;
+ }
+
+ _root = readnode(xmlDocGetRootElement(doc));
+ xmlFreeDoc(doc);
+ _initialized = true;
+
+ return true;
+}
+
+bool
+XMLTree::write(void) const
+{
+ xmlDocPtr doc;
+ XMLNodeList children;
+ int result;
+
+ xmlKeepBlanksDefault(0);
+ doc = xmlNewDoc((xmlChar *) "1.0");
+ xmlSetDocCompressMode(doc, _compression);
+ writenode(doc, _root, doc->children, 1);
+ result = xmlSaveFormatFile(_filename.c_str(), doc, 1);
+ xmlFreeDoc(doc);
+
+ if (result == -1)
+ return false;
+
+ return true;
+}
+
+void
+XMLTree::debug(FILE* out) const
+{
+ xmlDocPtr doc;
+ XMLNodeList children;
+
+ xmlKeepBlanksDefault(0);
+ doc = xmlNewDoc((xmlChar *) "1.0");
+ xmlSetDocCompressMode(doc, _compression);
+ writenode(doc, _root, doc->children, 1);
+ xmlDebugDumpDocument (out, doc);
+ xmlFreeDoc(doc);
+}
+
+const string &
+XMLTree::write_buffer(void) const
+{
+ static string retval;
+ char *ptr;
+ int len;
+ xmlDocPtr doc;
+ XMLNodeList children;
+
+ xmlKeepBlanksDefault(0);
+ doc = xmlNewDoc((xmlChar *) "1.0");
+ xmlSetDocCompressMode(doc, _compression);
+ writenode(doc, _root, doc->children, 1);
+ xmlDocDumpMemory(doc, (xmlChar **) & ptr, &len);
+ xmlFreeDoc(doc);
+
+ retval = ptr;
+
+ free(ptr);
+
+ return retval;
+}
+
+XMLNode::XMLNode(const string & n)
+ : _name(n), _is_content(false), _content(string())
+{
+
+ if (_name.empty())
+ _initialized = false;
+ else
+ _initialized = true;
+}
+
+XMLNode::XMLNode(const string & n, const string & c)
+ :_name(string()), _is_content(true), _content(c)
+{
+ _initialized = true;
+}
+
+XMLNode::XMLNode(const XMLNode& from)
+ : _initialized(false)
+{
+ XMLPropertyList props;
+ XMLPropertyIterator curprop;
+ XMLNodeList nodes;
+ XMLNodeIterator curnode;
+
+ _name = from.name();
+ set_content(from.content());
+
+ props = from.properties();
+ for (curprop = props.begin(); curprop != props.end(); curprop++)
+ add_property((*curprop)->name(), (*curprop)->value());
+
+ nodes = from.children();
+ for (curnode = nodes.begin(); curnode != nodes.end(); curnode++)
+ add_child_copy(**curnode);
+}
+
+XMLNode::~XMLNode()
+{
+ XMLNodeIterator curchild;
+ XMLPropertyIterator curprop;
+
+ for (curchild = _children.begin(); curchild != _children.end();
+ curchild++)
+ delete *curchild;
+
+ for (curprop = _proplist.begin(); curprop != _proplist.end();
+ curprop++)
+ delete *curprop;
+}
+
+const string &
+XMLNode::set_content(const string & c)
+{
+ if (c.empty())
+ _is_content = false;
+ else
+ _is_content = true;
+
+ _content = c;
+
+ return _content;
+}
+
+const XMLNodeList &
+XMLNode::children(const string & n) const
+{
+ static XMLNodeList retval;
+ XMLNodeConstIterator cur;
+
+ if (n.length() == 0)
+ return _children;
+
+ retval.erase(retval.begin(), retval.end());
+
+ for (cur = _children.begin(); cur != _children.end(); cur++)
+ if ((*cur)->name() == n)
+ retval.insert(retval.end(), *cur);
+
+ return retval;
+}
+
+XMLNode *
+XMLNode::add_child(const string & n)
+{
+ return add_child_copy(XMLNode (n));
+}
+
+void
+XMLNode::add_child_nocopy (XMLNode& n)
+{
+ _children.insert(_children.end(), &n);
+}
+
+XMLNode *
+XMLNode::add_child_copy(const XMLNode& n)
+{
+ XMLNode *copy = new XMLNode (n);
+ _children.insert(_children.end(), copy);
+ return copy;
+}
+
+XMLNode *
+XMLNode::add_content(const string & c)
+{
+ return add_child_copy(XMLNode (string(), c));
+}
+
+XMLProperty *
+XMLNode::property(const string & n)
+{
+ if (_propmap.find(n) == _propmap.end())
+ return 0;
+ return _propmap[n];
+}
+
+XMLProperty *
+XMLNode::add_property(const string & n, const string & v)
+{
+ if(_propmap.find(n) != _propmap.end()){
+ remove_property(n);
+ }
+
+ XMLProperty *tmp = new XMLProperty(n, v);
+
+ if (!tmp)
+ return 0;
+
+ _propmap[tmp->name()] = tmp;
+ _proplist.insert(_proplist.end(), tmp);
+
+ return tmp;
+}
+
+void
+XMLNode::remove_property(const string & n)
+{
+ if (_propmap.find(n) != _propmap.end()) {
+ _proplist.remove(_propmap[n]);
+ _propmap.erase(n);
+ }
+}
+
+void
+XMLNode::remove_nodes(const string & n)
+{
+ XMLNodeIterator i = _children.begin();
+ XMLNodeIterator tmp;
+
+ while (i != _children.end()) {
+ tmp = i;
+ ++tmp;
+ if ((*i)->name() == n) {
+ _children.erase (i);
+ }
+ i = tmp;
+ }
+}
+
+void
+XMLNode::remove_nodes_and_delete(const string & n)
+{
+ XMLNodeIterator i = _children.begin();
+ XMLNodeIterator tmp;
+
+ while (i != _children.end()) {
+ tmp = i;
+ ++tmp;
+ if ((*i)->name() == n) {
+ delete *i;
+ _children.erase (i);
+ }
+ i = tmp;
+ }
+}
+
+XMLProperty::XMLProperty(const string &n, const string &v)
+ : _name(n),
+ _value(v)
+{
+}
+
+XMLProperty::~XMLProperty()
+{
+}
+
+static XMLNode *
+readnode(xmlNodePtr node)
+{
+ string name, content;
+ xmlNodePtr child;
+ XMLNode *tmp;
+ xmlAttrPtr attr;
+
+ if (node->name)
+ name = (char *) node->name;
+ else
+ name = string();
+
+ tmp = new XMLNode(name);
+
+ for (attr = node->properties; attr; attr = attr->next) {
+ name = (char *) attr->name;
+ content = "";
+ if (attr->children)
+ content = (char *) attr->children->content;
+ tmp->add_property(name, content);
+ }
+
+ if (node->content)
+ tmp->set_content((char *) node->content);
+ else
+ tmp->set_content(string());
+
+ for (child = node->children; child; child = child->next)
+ tmp->add_child_nocopy (*readnode(child));
+
+ return tmp;
+}
+
+static void
+writenode(xmlDocPtr doc, XMLNode * n, xmlNodePtr p, int root =
+ 0)
+{
+ XMLPropertyList props;
+ XMLPropertyIterator curprop;
+ XMLNodeList children;
+ XMLNodeIterator curchild;
+ xmlNodePtr node;
+
+ if (root)
+ node = doc->children =
+ xmlNewDocNode(doc, 0, (xmlChar *) n->name().c_str(), 0);
+
+ else
+ node = xmlNewChild(p, 0, (xmlChar *) n->name().c_str(), 0);
+
+ if (n->is_content()) {
+ node->type = XML_TEXT_NODE;
+ xmlNodeSetContentLen(node, (const xmlChar *) n->content().c_str(),
+ n->content().length());
+ }
+
+ props = n->properties();
+ for (curprop = props.begin(); curprop != props.end(); curprop++)
+ xmlSetProp(node, (xmlChar *) (*curprop)->name().c_str(),
+ (xmlChar *) (*curprop)->value().c_str());
+
+ children = n->children();
+ for (curchild = children.begin(); curchild != children.end();
+ curchild++)
+ writenode(doc, *curchild, node);
+}