diff options
author | Taybin Rutkin <taybin@taybin.com> | 2005-05-13 20:47:18 +0000 |
---|---|---|
committer | Taybin Rutkin <taybin@taybin.com> | 2005-05-13 20:47:18 +0000 |
commit | d09f6b3016bacbc2871a8946cbb24ad705076509 (patch) | |
tree | f27312839c2a772cb2ce068a4f28b2449ad869df /libs/pbd3 |
Initial revision
git-svn-id: svn://localhost/trunk/ardour2@4 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd3')
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 ®exp, + 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 ®exp, + 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 Binary files differnew file mode 100644 index 0000000000..5008ddfcf5 --- /dev/null +++ b/libs/pbd3/pbd/.DS_Store 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 ®exp, + bool match_fullpath = true, + bool return_fullpath = true, + long limit = -1); + + + string *find_first (const string &dirpath, + const string ®exp, + 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); +} |